如何在Retrofit GET请求中发送对象参数?

如何在Retrofit GET请求中发送对象参数?

问题描述:

我有一个是这样的如何在Retrofit GET请求中发送对象参数?

"api/videos?search_object={"cat_id" :2, "channel_id" : 3, etc} 

Basily后端服务器,你可以给作为输入搜索对象,它会筛选对象的名单基地。现在我想的东西与改造要使用这项服务这样

@GET("videos") 
Call<VideoListResponse> listVideos(@Query("search_object") VideoSearchObject videoSearchObject); 

但上面的代码不工作,我可以先转换VideoSearchModel给它传递加装这样

@GET("videos") 
Call<VideoListResponse> listVideos(@Query("search_object") String jsonString); 
JSON字符串

我想知道是否有更好的更清晰的方法?任何建议将不胜感激。

+0

如果你想在查询中发送json字符串,恐怕这是唯一的方法。 –

"api/videos?search_object={"cat_id" :2, "channel_id" : 3, etc} 

基本上可以给出搜索对象作为输入

不,你不给一个对象作为输入。您提供了包含在{ }中的多个参数,以便它看起来像对象(不是Java对象的JavaScript对象)。实际上它只是一个字符串。

构造的url只是一串字符。在url中不存在“对象”这样的东西。

继续做下去就像@Query("search_object") String jsonString。虽然您可能也想要将参数jsonString重命名为searchString,因为这就是它的原因。它不是JSON字符串。一个JSON字符串可以让所有"字符像\"一样被转义。

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总是与 “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://任何/ API /视频X = {%22k1%22:%22v1%22%部22k2附近%22:%22v2%22}

X参数参数是一个编码表示{"k1":"v1","k2":"v2"}