OkHttp スタックを使用してボレー リクエスト ( または のいずれStringRequest
かJsonObjectRequest
) を実行すると、応答文字列のエンコーディングがデフォルトのエンコーディングである ISO-8995-1 に設定されます。応答にはヘッダーがあります: content-type=text/html; charset=utf-8
、これを検出する必要があります。なぜそうではないのですか?
5 に答える
これらのリクエスト タイプは両方ともHttpHeaderParser.parseCharset
、ヘッダーから文字セットを決定できる を呼び出します。Content-Type
ただし、ヘッダーはではなくである必要がありcontent-type
ます。大文字と小文字が区別されます。(デフォルトの HurlStack を使用した場合の動作はわかりません。これは、OkHttp スタックとの実装の詳細の違いである可能性があります。)
解決策 1: 元のリクエスト タイプをコピーしますが、文字セットを手動で上書きします
解決策 2: 元のリクエスト タイプをコピーしますが、予期されるヘッダーが存在するように強制します
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
public class JsonUTF8Request extends JsonRequest<JSONObject> {
public JsonUTF8Request(int method, String url, JSONObject jsonRequest,
Listener<JSONObject> listener, ErrorListener errorListener) {
super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener,
errorListener);
}
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
// solution 1:
String jsonString = new String(response.data, "UTF-8");
// solution 2:
response.headers.put(HTTP.CONTENT_TYPE,
response.headers.get("content-type"));
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
//
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
最初に、ここに投稿した2つのソリューションについて@mjibsonに感謝します。同様の問題がありました。私の場合、コンテンツタイプが常に欠落していたため、次のようにしました。
protected static final String TYPE_UTF8_CHARSET = "charset=UTF-8";
@Override
protected Response<String> parseNetworkResponse(
NetworkResponse response) {
try {
String type = response.headers.get(HTTP.CONTENT_TYPE);
if (type == null) {
Log.d(LOG_TAG, "content type was null");
type = TYPE_UTF8_CHARSET;
response.headers.put(HTTP.CONTENT_TYPE, type);
} else if (!type.contains("UTF-8")) {
Log.d(LOG_TAG, "content type had UTF-8 missing");
type += ";" + TYPE_UTF8_CHARSET;
response.headers.put(HTTP.CONTENT_TYPE, type);
}
} catch (Exception e) {
//print stacktrace e.g.
}
return super.parseNetworkResponse(response);
}
他の人が同様の問題に遭遇するためにこれを共有したかっただけです。https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/HttpHeaderParser.javaの parseCharset メソッドを読んで、これが機能する理由を理解することも重要です
ありがとう@Simon Heinen。あなたの返信に基づいて、関数を書きました。
private void addEncodeing2Request(NetworkResponse response) {
try {
String type = response.headers.get(HTTP.CONTENT_TYPE);
if (type == null) {
//Content-Type:
Log.d("RVA", "content type was null");
type = TYPE_UTF8_CHARSET;
response.headers.put(HTTP.CONTENT_TYPE, type);
} else if (!type.contains("charset")) {
//Content-Type: text/plain;
Log.d("RVA", "charset was null, added encode utf-8");
type += ";" + TYPE_UTF8_CHARSET;
response.headers.put(HTTP.CONTENT_TYPE, type);
} else {
//nice! Content-Type: text/plain; charset=utf-8'
Log.d("RVA", "charset is " + type);
}
} catch (Exception e) {
e.printStackTrace();
}
}
使用法:
protected Response<String> parseNetworkResponse(NetworkResponse response) {
addEncodeing2Request(response);
return super.parseNetworkResponse(response);
}
さらに、オーバーライド getParamsEncoding() も機能する場合があります。
protected String getParamsEncoding() {
return "utf-8";
}