You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit创建URL时如何避免@QueryMap中&被编码为%26?

解决Retrofit中@QueryMap参数包含"&"不被编码的问题

我完全懂你的困扰——当@QueryMap里的参数值自带"&"符号时,Retrofit默认的URL编码会把它转成"%26",导致接口请求的参数不符合预期,而且你试过常规的编码设置没搞定对吧?下面给你几个经过验证的可行方案:

方案一:用OkHttp拦截器手动修正URL(最推荐)

这个方法灵活且可控,能在请求发送前把被编码的"%26"替换回原始的"&",不影响其他参数的正常编码。

先创建一个拦截器:

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            HttpUrl originalUrl = originalRequest.url();

            // 检查查询字符串里是否有被编码的&
            String queryStr = originalUrl.query();
            if (queryStr != null && queryStr.contains("%26")) {
                // 将%26替换回&,保留原始符号
                String modifiedQuery = queryStr.replace("%26", "&");
                // 构建新的URL
                HttpUrl modifiedUrl = originalUrl.newBuilder()
                        .query(modifiedQuery)
                        .build();
                // 替换原请求的URL
                Request modifiedRequest = originalRequest.newBuilder()
                        .url(modifiedUrl)
                        .build();
                return chain.proceed(modifiedRequest);
            }
            return chain.proceed(originalRequest);
        }
    })
    .build();

然后把这个自定义的OkHttpClient传给Retrofit:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(AppConstants.BASE_URL)
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build();

这样一来,所有经过这个client的请求,都会自动把查询参数里的"%26"还原成"&",完全不影响你的原有接口定义。

方案二:自定义URL编码器(针对性处理)

如果你只想对特定参数的&不编码,可以自定义一个Encoder,替换Retrofit的默认编码逻辑:

public class CustomQueryEncoder implements Encoder {
    private final Encoder defaultEncoder = new DefaultEncoder();

    @Override
    public String encode(String input) throws UnsupportedEncodingException {
        // 先让默认编码器处理其他特殊字符,再把&的编码结果替换回来
        String encoded = defaultEncoder.encode(input);
        return encoded.replace("%26", "&");
    }
}

然后在构建Retrofit的时候,通过@QueryMap的encoder参数指定这个自定义编码器:

@GET(AppConstants.BASE_URL + "{category_type}/")
Call<JsonObject> callCustomFilterApI(
    @Path("category_type") String type,
    @QueryMap(encoded = true, encoder = CustomQueryEncoder.class) Map<String,String> fields,
    @Query("page") String pageNo
);

不过要注意,这个方法会对整个@QueryMap里的所有参数生效,如果只有个别参数需要保留&,可能需要在自定义Encoder里加判断逻辑。

方案三:手动拼接URL(适合参数较少的场景)

如果你的参数数量不多,可以放弃@QueryMap,改用@Url注解手动拼接完整请求URL,这样能完全控制参数的格式:

@GET
Call<JsonObject> callCustomFilterApI(@Url String fullUrl);

调用的时候手动组装URL:

// 示例参数
String categoryType = "books";
String pageNo = "2";
Map<String, String> fields = new HashMap<>();
fields.put("filter", "price>10&stock>0"); // 这里的&直接保留

// 手动拼接查询参数
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("page=").append(pageNo);
for (Map.Entry<String, String> entry : fields.entrySet()) {
    queryBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}

String fullUrl = AppConstants.BASE_URL + categoryType + "/" + "?" + queryBuilder.toString();
// 发起请求
yourApiService.callCustomFilterApI(fullUrl);

这个方法的好处是完全可控,但要注意除了需要保留的&之外,其他特殊字符(比如空格、中文)还是需要手动编码,避免出现URL格式错误。

最后提醒一句:要确保后端接口能正确解析这种带&的参数值——如果你的参数值里的&是用来表示多个子条件(比如filter=price>10&stock>0),后端需要能把整个字符串当成一个参数值来处理,而不是把stock>0当成另一个独立参数。

内容的提问来源于stack exchange,提问作者Ankur_009

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:10:46