如何使用Retrofit实现带方括号格式的GET请求查询参数?
Retrofit处理带方括号的GET请求参数解决方案
我有一个包含多个参数的GET请求URL:
https://www.games.com/game?filter[condition][path]=season&filter[condition][value]=Season1&page[limit]=1&page[offset]=0尝试用Retrofit实现参数化调用时遇到问题,使用以下代码无法让Retrofit识别这类方括号格式的参数:
@Headers("Content-Type: application/json") @GET("game") Call<FunctionsResponse> getAllGames( @Query("filter[condition][path]") String conditionFilter, @Query("filter[condition][value]") String conditionValue, @Query("page[limit]") String pageLimit, @Query("page[offset]") String pageOffset );
方法一:使用@QueryMap嵌套映射
这是最推荐的方式,Retrofit支持通过嵌套Map自动生成带方括号的层级参数:
@Headers("Content-Type: application/json") @GET("game") Call<FunctionsResponse> getAllGames(@QueryMap Map<String, Object> params);
调用时构建嵌套结构的Map:
// 构建条件参数 Map<String, Object> condition = new HashMap<>(); condition.put("path", "season"); condition.put("value", "Season1"); Map<String, Object> filter = new HashMap<>(); filter.put("condition", condition); // 构建分页参数 Map<String, Object> page = new HashMap<>(); page.put("limit", "1"); page.put("offset", "0"); // 整合所有参数 Map<String, Object> params = new HashMap<>(); params.put("filter", filter); params.put("page", page); // 调用接口 Call<FunctionsResponse> call = apiService.getAllGames(params);
方法二:手动转义方括号
如果偏好单个@Query参数的写法,可以将方括号替换为URL转义符%5B(左括号)和%5D(右括号):
@Headers("Content-Type: application/json") @GET("game") Call<FunctionsResponse> getAllGames( @Query("filter%5Bcondition%5D%5Bpath%5D") String conditionFilter, @Query("filter%5Bcondition%5D%5Bvalue%5D") String conditionValue, @Query("page%5Blimit%5D") String pageLimit, @Query("page%5Boffset%5D") String pageOffset );
不过这种写法可读性较差,不推荐在复杂参数场景下使用。
方法三:自定义OkHttp拦截器
通过拦截器在请求发送前手动拼接参数,适合需要动态处理复杂参数逻辑的场景:
public class CustomParamInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); HttpUrl originalUrl = originalRequest.url(); // 手动拼接带方括号的参数 HttpUrl newUrl = originalUrl.newBuilder() .addQueryParameter("filter[condition][path]", "season") .addQueryParameter("filter[condition][value]", "Season1") .addQueryParameter("page[limit]", "1") .addQueryParameter("page[offset]", "0") .build(); Request newRequest = originalRequest.newBuilder() .url(newUrl) .build(); return chain.proceed(newRequest); } }
初始化Retrofit时添加该拦截器:
OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(new CustomParamInterceptor()) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.games.com/") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build();
内容的提问来源于stack exchange,提问作者Nexussim Lements
相关产品推荐
相关产品推荐

