How to specify Get-Request encoding (Retrofit + OkHttp)

14,508

One way to do this is to build an Interceptor that takes the response and sets an appropriate Content-Type like so:

class ResponseInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val response = chain.proceed(chain.request())
        val modified = response.newBuilder()
                .addHeader("Content-Type", "application/json; charset=utf-8")
                .build()

        return modified
    }
}

You would add it to your OkHttp client like so:

val client = OkHttpClient.Builder()
        .addInterceptor(ResponseInterceptor())
        .build()

You should make sure you either only use this OkHttpClient for your API that has no encoding specified, or have the interceptor only add the header for the appropriate endpoints to avoid overwriting valid content type headers from other endpoints.

Share:
14,508

Related videos on Youtube

xani
Author by

xani

computer science student

Updated on September 15, 2022

Comments

  • xani
    xani over 1 year

    I'm using Retrofit2 + OkHttp3 in my Android app to make a GET - Request to a REST-Server. The problem is that the server doesn't specify the encoding of the JSON it delivers. This results in an 'é' being received as '�' (the Unicode replacement character).

    Is there a way to tell Retrofit or OkHttp which encoding the response has?

    This is how I initialize Retrofit (Kotlin code):

    val gson = GsonBuilder()
            .setDateFormat("d.M.yyyy")
            .create()
    
    val client = OkHttpClient.Builder()
            .build()
    
    val retrofit = Retrofit.Builder()
            .baseUrl(RestService.BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
    
    val rest = retrofit.create(RestService::class.java)
    

    PS: The server isn't mine. So I cannot fix the initial problem on the server side.

    Edit: The final solution

    class EncodingInterceptor : Interceptor {
    
        override fun intercept(chain: Interceptor.Chain): Response {
            val response = chain.proceed(chain.request())
            val mediaType = MediaType.parse("application/json; charset=iso-8859-1")
            val modifiedBody = ResponseBody.create(mediaType, response.body().bytes())
            val modifiedResponse = response.newBuilder()
                    .body(modifiedBody)
                    .build()
    
            return modifiedResponse
        }
    }
    
  • xani
    xani almost 7 years
    Wow, that was fast. Now I only have to find out what encoding they are using ;) Thanks for that.
  • xani
    xani almost 7 years
    It seems like OkHttp is ignoring the charset I set. Even after removing the old Content-Type: application/json before adding the correct one. However I was able to get manuelly the correct string by using InputStreamReader(response.body().byteStream(), "ISO-8859-1").readText() in the interceptor. But I was not able to add this to the modified Response.
  • xani
    xani almost 7 years
    My third and last comment ;) I got it working and added the solution to my question. Thanks for showing me how interceptors work.
  • Bryan Herbst
    Bryan Herbst almost 7 years
    Glad you got it working! I was just looking at it and realized that you'd need to re-create the ResponseBody, but you found it first!