java 为什么 Retrofit 不能正确编码带方括号的查询字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26129697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why Retrofit cannot encode properly query string with square brackets?
提问by Noodles
I'm using Retrofit for my network layer in my Android app, but I have a problem with the URL encoding.
我在我的 Android 应用程序中为我的网络层使用 Retrofit,但我遇到了 URL 编码问题。
I have to call an REST API like that:
我必须像这样调用 REST API:
https://my_hostname.com/some_path?q=some_query¶m[0]=value1¶m[1]=value2&other_param=abcd
as you can see the query string is composed by some different kind of parameters, so I decided to use the @QueryMap
annotation in the Retrofit Interface with a Map<String, String>
where
q, param[1], param[0], other_param
are String keys of the map
正如您所看到的,查询字符串由一些不同类型的参数组成,因此我决定使用@QueryMap
Retrofit Interface 中的注释,Map<String, String>
其中
q, param[1], param[0], other_param
包含地图的字符串键
What do I expect?
I expect the square brackets in the URL are encoded with %5B
for '['
and %5D
for '['
, but this does not happen.
我期待什么?我希望 URL 中的方括号用%5B
for'['
和%5D
for编码'['
,但这不会发生。
Why does this happen? The square brackets should be encoded with percent encoding. Is this a bug or I'm doing something wrong? I also tried the @EncodedQueryMap
annotation with no differences.
为什么会发生这种情况?方括号应使用百分比编码进行编码。这是一个错误还是我做错了什么?我也尝试了@EncodedQueryMap
没有区别的注释。
回答by Jake Wharton
Query names are never URL encoded.
查询名称从不进行 URL 编码。
The documentation for @QueryMap
states:
@QueryMap
状态的文档:
Values are URL encoded.
值是 URL 编码的。
And for @EncodedQueryMap
:
而对于@EncodedQueryMap
:
Values are not URL encoded.
值不是 URL 编码的。
However, I just submitted a pull requestto change this behavior a bit. I am adding support for encoding keys by using @Query(value = "..", encodeName = true)
or @QueryMap(encodeNames = true)
.
但是,我只是提交了一个拉取请求来稍微改变这种行为。我正在通过使用@Query(value = "..", encodeName = true)
或添加对编码密钥的支持@QueryMap(encodeNames = true)
。
回答by etherton
I just had to deal with @QueryMap
encoding everything but {}[]
. Most of the time I don't mind because I rarely send json in the query, and want to push the encoding down as low as possible in my application's stack, but recently I had to add an endpoint just like Ivan describes. My solution was to add an interceptor that does this:
我只需要处理@QueryMap
所有内容的编码,但{}[]
. 大多数时候我不介意,因为我很少在查询中发送 json,并且希望在我的应用程序堆栈中尽可能降低编码,但最近我不得不像 Ivan 描述的那样添加一个端点。我的解决方案是添加一个执行此操作的拦截器:
Request originalRequest = chain.request();
HttpUrl url = originalRequest.url();
String urlFilePath = url.encodedPath();
if(url.encodedQuery() != null) {
// Because Retrofit doesn't think "{}[]" should be encoded
// but our API does
String correctlyEncodedQuery = correctlyEncodeQuery(url);
urlFilePath += "?" + correctlyEncodedQuery;
}
URL correctUrl = new URL(url.scheme(), url.host(), url.port(),
urlFilePath);
Request newRequest = originalRequest.newBuilder()
.url(correctUrl)
private String correctlyEncodeQuery(HttpUrl url) throws UnsupportedEncodingException {
String retVal = "";
for(String queryKey : url.queryParameterNames()){
if(retVal.length() > 0){
retVal += "&";
}
String queryValue = url.queryParameter(queryKey);
retVal += queryKey + "=" + URLEncoder.encode(queryValue, "utf-8");
}
return retVal;
}
回答by Swapnil Kshirsagar
Try simple one @GET and parameters @Query
尝试简单的@GET 和参数@Query
回答by Ivan Trechyokas
Moreover, if value contains JSONArray with JSONObject, retrofit doesn't encode brackets [ ] { }
此外,如果 value 包含带有 JSONObject 的 JSONArray,retrofit 不会编码方括号 [] { }
Map contains element:
地图包含元素:
key = filter,
value = [{"field":"some_field","value":"some_value","operator":"="}]
And @QueryMap send
和@QueryMap 发送
http://my_server/api?filter=[{%22field%22:%22some_field%22,%22value%22:%22some_value%22,%22operator%22:%22%3D%22}]
QueryMap used there because of number params in GET request and objects in filter option.
由于 GET 请求中的数字参数和过滤器选项中的对象,在那里使用了 QueryMap。