web-dev-qa-db-ja.com

Get-Requestエンコーディングを指定する方法(Retrofit + OkHttp)

AndroidアプリでGET-RESTサーバーへのリクエストを作成するためにRetrofit2 + OkHttp3を使用しています。問題は、サーバーが配信するJSONのエンコーディングを指定していないことです。これにより、「é」が「�」(Unicode置換文字)として受信されます。

応答のエンコーディングをRetrofitまたはOkHttpに通知する方法はありますか?

これは私がレトロフィット(Kotlinコード)を初期化する方法です:

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:サーバーは私のものではありません。したがって、サーバー側の最初の問題を修正することはできません。

編集:最終的な解決策

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
    }
}
9
Alexander

これを行う1つの方法は、応答を受け取って適切なContent-Typeを設定するInterceptorを作成することです。

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
    }
}

次のようにOkHttpクライアントに追加します。

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

エンコードが指定されていないAPIに対してのみこのOkHttpClientを使用するか、適切なエンドポイントのヘッダーのみをインターセプターに追加して、他のエンドポイントから有効なコンテンツタイプヘッダーが上書きされないようにする必要があります。

7
Bryan Herbst
class FixEncodingInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        MediaType oldMediaType = MediaType.parse(response.header("Content-Type"));
        // update only charset in mediatype
        MediaType newMediaType = MediaType.parse(oldMediaType.type()+"/"+oldMediaType.subtype()+"; charset=windows-1250");
        // update body
        ResponseBody newResponseBody = ResponseBody.create(newMediaType, response.body().bytes());

        return response.newBuilder()
                .removeHeader("Content-Type")
                .addHeader("Content-Type", newMediaType.toString())
                .body(newResponseBody)
                .build();
    }
}

okHttpに追加します。

builder.addInterceptor(new FixEncodingInterceptor());
0
Michał Ciołek