Rez*_*adi 7 android gson android-networking retrofit retrofit2
我有一个像这样的后端服务器
"api/videos?search_object={"cat_id" :2, "channel_id" : 3, etc}
Run Code Online (Sandbox Code Playgroud)
您可以轻松地将搜索对象作为输入,它会基于该对象过滤列表。现在,我想将此服务与Retrofit一起使用,就像这样
@GET("videos")
Call<VideoListResponse> listVideos(@Query("search_object") VideoSearchObject videoSearchObject);
Run Code Online (Sandbox Code Playgroud)
但是上面的代码不起作用,我可以先将VideoSearchModel转换为JSON字符串,然后将其传递给它进行改造
@GET("videos")
Call<VideoListResponse> listVideos(@Query("search_object") String jsonString);
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更好更好的方法?任何建议将不胜感激。
改造2支持它。您所要做的就是使用stringConverter()重写的方法实现自定义转换器工厂。
考虑以下带有自定义批注的Retrofit-friendly界面:
@Target(PARAMETER)
@Retention(RUNTIME)
@interface ToJson {
}
Run Code Online (Sandbox Code Playgroud)
interface IService {
    @GET("api/videos")
    Call<Void> get(
            @ToJson @Query("X") Map<String, Object> request
    );
}
Run Code Online (Sandbox Code Playgroud)
批注用于表示必须转换为字符串的参数。
模拟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();
Run Code Online (Sandbox Code Playgroud)
private static final Gson gson = new Gson();
Run Code Online (Sandbox Code Playgroud)
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();
Run Code Online (Sandbox Code Playgroud)
要对其进行测试,您可以简单地调用服务接口方法:
final IService service = retrofit.create(IService.class);
service.get(ImmutableMap.of("k1", "v1", "k2", "v2")).execute();
Run Code Online (Sandbox Code Playgroud)
结果:
http:// whatever / api / videos?X = {%22k1%22:%22v1%22,%22k2%22:%22v2%22}
其中X参数参数是的编码表示形式{"k1":"v1","k2":"v2"}。
Run Code Online (Sandbox Code Playgroud)"api/videos?search_object={"cat_id" :2, "channel_id" : 3, etc}基本上你可以给出一个搜索对象作为输入
不,您不提供对象作为输入。您提供包含在其中的多个参数{ },使其看起来像一个对象(JavaScript 对象,而不是 Java 对象)。实际上它只是一个字符串。
构造的 url 只是一堆字符。url 中不存在“对象”这样的东西。
继续这样做@Query("search_object") String jsonString。尽管您可能还想将参数从jsonString重命名为searchString,因为它就是这样。它不是 JSON 字符串。JSON 字符串的所有"字符都会像\".
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           4778 次  |  
        
|   最近记录:  |