Search code examples
javaandroidjsonretrofit2

Retrofit 2: @Query "encoded=false" doesn't work


  1. I am using Retrofit 2 for work with Bank API.

  2. I have some interface:

public interface ApiService {
    @GET("statdirectory/exchange")
    Call<List<MyModel>>  getСurrency(@Query("date") String inputDate);
}
  1. 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()+"");      
}
//.....
  1. I see that:

URL: *"https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?
date=20170917**%26**json"* (**&** is replaced by **%26**)
CODE: *"404"*

  1. In my interface I add encoded:
getСurrency(@Query(value="date", encoded=false) String inputDate);

But my result is the same as in step 3!

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

Solution

  • 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());