我有一个像这样工作的后端服务器
"api/videos?search_object={"cat_id" :2, "channel_id" : 3, etc}
基本上,您可以将搜索对象作为输入,它将过滤该对象的列表。现在我想将此服务与Retrofit一起用于此类
@GET("videos")
Call<VideoListResponse> listVideos(@Query("search_object") VideoSearchObject videoSearchObject);
但上面的代码不起作用,我可以先将VideoSearchModel转换为JSON字符串,将其传递给这样的改造
@GET("videos")
Call<VideoListResponse> listVideos(@Query("search_object") String jsonString);
我想知道是否有更清晰的方式?任何建议将不胜感激。
答案 0 :(得分:5)
Retrofit 2支持它。您所要做的就是实现自定义转换器工厂,并覆盖stringConverter()
方法。
考虑以下带有自定义注释的易于改造的界面:
@Target(PARAMETER)
@Retention(RUNTIME)
@interface ToJson {
}
interface IService {
@GET("api/videos")
Call<Void> get(
@ToJson @Query("X") Map<String, Object> request
);
}
注释用于表示必须转换为字符串的参数。
模拟OkHttpClient
始终响应&#34; HTTP 200 OK&#34;和转储请求网址:
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://任何/ API /视频X = {%22k1%22:%22v1%22%部22k2附近%22:%22v2%22}?
X
参数参数是{"k1":"v1","k2":"v2"}
的编码表示。
答案 1 :(得分:0)
"api/videos?search_object={"cat_id" :2, "channel_id" : 3, etc}
基本上,您可以将搜索对象作为输入
不,您不会将对象作为输入。您提供了{ }
中包含的多个参数,以使其看起来像一个对象(一个JavaScript对象,而不是Java对象)。实际上它只是一个字符串。
构建的url只是一堆字符。网址中没有“对象”这样的东西。
继续像@Query("search_object") String jsonString
那样做。虽然您可能还想将参数从jsonString
重命名为searchString
,但这就是它。它不是JSON字符串。 JSON字符串会像"
一样转义所有\"
个字符。