Retrofit 2支持此功能。您只需实现一个自定义转换器工厂,并覆盖
stringConverter()
方法即可。
考虑以下带有自定义注释的Retrofit友好接口:
@Target(PARAMETER)
@Retention(RUNTIME)
@interface ToJson {
}
interface IService {
@GET("api/videos")
Call<Void> get(
@ToJson @Query("X") Map<String, Object> request
);
}
注解用于表示必须转换为字符串的参数。
模拟 OkHttpClient
总是响应“HTTP 200 OK”并转储请求URL:
private static final OkHttpClient mockHttpClient = new OkHttpClient.Builder()
.addInterceptor(chain -> {
System.out.println(chain.request().url());
return new Response.Builder()
.request(chain.request())
.protocol(HTTP_1_0)
.code(HTTP_OK)
.body(ResponseBody.create(MediaType.parse("application/json"), "OK"))
.build();
})
.build();
private static final Gson gson = new Gson();
private static final Retrofit retrofit = new Retrofit.Builder()
.client(mockHttpClient)
.baseUrl("http://whatever")
.addConverterFactory(new Converter.Factory() {
@Override
public Converter<?, String> stringConverter(final Type type, final Annotation[] annotations, final Retrofit retrofit) {
if ( !hasToJson(annotations) ) {
return super.stringConverter(type, annotations, retrofit);
}
return value -> gson.toJson(value, type);
}
private boolean hasToJson(final Annotation[] annotations) {
for ( final Annotation annotation : annotations ) {
if ( annotation instanceof ToJson ) {
return true;
}
}
return false;
}
})
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
要测试它,您可以简单地调用服务接口方法:
final IService service = retrofit.create(IService.class);
service.get(ImmutableMap.of("k1", "v1", "k2", "v2")).execute();
结果:
http://whatever/api/videos?X={%22k1%22:%22v1%22,%22k2%22:%22v2%22}
X
参数的取值是编码过的 {"k1":"v1","k2":"v2"}
表示。