问题
I'm using Retrofit for my network layer in my Android app, but I have a problem with the URL encoding.
I have to call an REST API like that:
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
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.
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.
回答1:
Query names are never URL encoded.
The documentation for @QueryMap
states:
Values are URL encoded.
And for @EncodedQueryMap
:
Values are not URL encoded.
However, I just submitted a pull request to change this behavior a bit. I am adding support for encoding keys by using @Query(value = "..", encodeName = true)
or @QueryMap(encodeNames = true)
.
回答2:
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:
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;
}
回答3:
Try simple one @GET and parameters @Query
回答4:
Moreover, if value contains JSONArray with JSONObject, retrofit doesn't encode brackets [ ] { }
Map contains element:
key = filter,
value = [{"field":"some_field","value":"some_value","operator":"="}]
And @QueryMap send
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.
来源:https://stackoverflow.com/questions/26129697/why-retrofit-cannot-encode-properly-query-string-with-square-brackets