Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
    }
}
like image 752
xani Avatar asked Jul 24 '17 15:07

xani


1 Answers

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.

like image 196
Bryan Herbst Avatar answered Sep 19 '22 16:09

Bryan Herbst