Retrofit 2: @Query “encoded=false” don't work

不羁的心 提交于 2020-08-24 05:30:42

问题


0) I am using Retrofit 2 for work with Bank API.
1) I have some interface:

public interface ApiService {
    @GET("statdirectory/exchange")
    Call<List<MyModel>>  getСurrency(@Query("date") String inputDate);
}

2) And when i call method getСurrency(someParametr), where someParametr is string, consist with "date&json" (for example, "20170917&json"):

ApiService apiService = RetrofitController.getApi();
apiService.getCurrency("20170917&json").enqueue(new Callback<List<MyModel>>() {

      @Override
      public void onResponse(Call<List<MyModel>> call, Response<List<MyModel>> response) {
          call.request().url();
          Log.e("URL",  call.request().url()+"");
          response.code();
          Log.e("CODE", response.code()+"");      
}
//.....

3) I see that:
URL: "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=20170917%26json" (& is replaced by %26)
CODE: "404"
4) Inmy interface i add encoded:

getСurrency(@Query(value="date", encoded=false) String inputDate);

But my result is the same as in step 3!

5) How to check this problem? How to get URL without %26 on my string? I read other questions with similar problem, but isn't solve my problem. Thanks!


回答1:


As noted here https://github.com/square/okhttp/issues/2623 by swankjesse

Use HttpUrl to build the url

HttpUrl url = HttpUrl.parse("https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=20170916&json");

Then change your method call to

@GET
Call<List<MyModel>>  getСurrency(@Url String ur);

Then

 apiService.getCurrency(url.toString())
       .enqueue(new Callback<List<MyModel>>() {

        @Override
        public void onResponse(Call<List<MyModel>> call, retrofit2.Response<List<MyModel>> response) {
            // your response
        }

        @Override
        public void onFailure(Call<List<MyModel>> call, Throwable t) {

        }

    });

Other way is to use Okhttp's Interceptor and replace %26 by &

class MyInterceptor implements Interceptor {
   @Override
   Response intercept(Interceptor.Chain chain) throws IOException {
    Request request = chain.request()
    String stringurl = request.url().toString()
    stringurl = stringurl.replace("%26", "&")

    Request newRequest = new Request.Builder()
        .url(stringurl)
        .build()

    return chain.proceed(newRequest)
 }
}

Then

 OkHttpClient client = new OkHttpClient.Builder();
 client.addInterceptor(new MyInterceptor());



回答2:


I just wanted to clarify that the original problem was that the encoded parameter needed to be true: encoded=true. This indicates that the value provided is already encoded and thus doesn't need to be re-encoded by retrofit. As is stated in the retrofit documentation, the default value of encoded is false. ie:

getСurrency(@Query(value="date", encoded=true) String inputDate);

will result in the correct url being generated.

The documentation states the following regarding the encoded parameter:

Specifies whether the parameter name and value are already URL encoded.

Source: https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/Query.html




回答3:


If you still got this problem, I have 2 solutions.

FIRST SOLUTION:

// Create a URL object and pass to constructor your url
URL urlObject = new URL(url);
// Create connection
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
// SET 'GET' request
connection.setRequestMethod("GET");
connection.connect();
// Create stream to read output
InputStream inputStream = connection.getInputStream();

// Craete buffer to gain all output
StringBuffer stringBuffer = new StringBuffer();
AND HERE IS THE KEY
YOU CREATE A BUFFERREADER AND SET CP1251 SO URL`S GONNA BE ENCODED
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "cp1251"));
// Read untill end
String line;
while ((line = bufferedReader.readLine()) != null) {
    stringBuffer.append(line);
}
// HERE IS YOUR JSON RESULT
resultJson = stringBuffer.toString();

SECOND SOLUTION:

Just add encoded = true to your @Query annotation

@GET("some_path")
    Call<RequestBody> function(@Query(value = "param", encoded = true) String your_param);

That's it! All that worked well for me. If you have some comments or questions, I will answer them.




回答4:


your Json will have key value data. Try to pass in below format. It will automatically add the & before Json key.

getСurrency(@Query("date") String inputDate, @Query("key1") String value1, @Query("key2") String value2);


来源:https://stackoverflow.com/questions/46277907/retrofit-2-query-encoded-false-dont-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!