Quando si esegue una richiesta di scarica (StringRequest
o JsonObjectRequest
), utilizzando lo stack OkHttp, la codifica della stringa di risposta è impostata su ISO-8995-1, che è la codifica predefinita. La risposta ha un'intestazione: content-type=text/html; charset=utf-8
, che dovrebbe essere rilevata. Perché non lo è?Perché la stringa di risposta di volley utilizza una codifica diversa da quella delle intestazioni di risposta?
risposta
Entrambi i tipi di richiesta chiamano HttpHeaderParser.parseCharset
, che è in grado di determinare il set di caratteri dalle intestazioni. Tuttavia, richiede che l'intestazione sia Content-Type
, non content-type
: è case sensitive. (Non sono sicuro del comportamento se si utilizza il default HurlStack, è possibile si tratta di una differenza di dettaglio di implementazione con lo stack OkHttp.)
Soluzione 1: copiare il tipo di richiesta originale, ma sostituire manualmente il set di caratteri
Soluzione 2: copiare il tipo di richiesta originale, ma forzare l'intestazione dovrebbe esistere
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));
}
}
}
Innanzitutto grazie a lot @mjibson per le 2 soluzioni hai postato qui, ho avuto un problema simile, nel mio caso il tipo di contenuto è stato manca sempre così ha fatto quanto segue:
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);
}
volevo solo condividere questo per gli altri per imbattersi in un problema simile. è inoltre importante leggere il metodo parseCharset in https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/HttpHeaderParser.java per ottenere il motivo per cui funziona
Ignorare il metodo parseNetworkResponse
della classe Request<T>
.
Si può fare in questo modo:
/**
* A canned request for retrieving the response body at a given URL as a String.
*/
public class StringRequest extends Request<String> {
private final Listener<String> mListener;
/**
* the parse charset.
*/
private String charset = null;
/**
* Creates a new request with the given method.
*
* @param method the request {@link Method} to use
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
* @param errorListener Error listener, or null to ignore errors
*/
public StringRequest(int method, String url, Listener<String> listener,
ErrorListener errorListener) {
super(method, url, errorListener);
mListener = listener;
}
/**
* Creates a new GET request.
*
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
* @param errorListener Error listener, or null to ignore errors
*/
public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {
this(Method.GET, url, listener, errorListener);
}
/**
* Creates a new GET request with the given Charset.
*
* @param url URL to fetch the string at
* @param listener Listener to receive the String response
* @param errorListener Error listener, or null to ignore errors
*/
public StringRequest(String url, String charset, Listener<String> listener, ErrorListener errorListener) {
this(Method.GET, url, listener, errorListener);
this.charset = charset;
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
if(charset != null) {
parsed = new String(response.data, charset);
} else {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
}
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
/**
* @return the Parse Charset Encoding
*/
public String getCharset() {
return charset;
}
/**
* set the Parse Charset Encoding
* @param charset
*/
public void setCharset(String charset) {
this.charset = charset;
}
}
cambiare il metodo da GET POST per UTF-8 suppport
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.POST,
URL_FEED, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, "Response: " + response.toString());
Log.d("SHY", "Response: " + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
. . . .
Grazie @Simon Heinen. In base alla tua risposta, ho scritto una funzione.
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();
}
}
utilizzati:
protected Response<String> parseNetworkResponse(NetworkResponse response) {
addEncodeing2Request(response);
return super.parseNetworkResponse(response);
}
Inoltre, ignorare getParamsEncoding() può anche funzionare.
protected String getParamsEncoding() {
return "utf-8";
}
- 1. Rimozione delle intestazioni dalla risposta
- 2. Ottenere intestazioni da una risposta al volo
- 3. Parse Android Volley JSONArray risposta
- 4. Risposta in streaming di Sinatra con intestazioni
- 5. Personalizzazione delle intestazioni di risposta nel middleware Wai
- 6. Ottenere intestazioni di risposta HTTP non corretti
- 7. Codifica risposta campione JMeter
- 8. Lettura AF Intestazioni di risposta alla rete
- 9. Recupera le intestazioni di risposta in Silverlight?
- 10. L'ordine delle intestazioni in una risposta HTTP è sempre importante?
- 11. Akka-http: Come impostare intestazioni di risposta
- 12. jQuery - ottiene le intestazioni di risposta AJAX
- 13. Invio della risposta di codifica in JSON
- 14. Come ottenere una risposta stringa da Retrofit2?
- 15. Modifica risposta HTML (non intestazioni)
- 16. Come ottenere le intestazioni di risposta completa da risorsa angolare
- 17. Perché la risposta del rack non è una stringa?
- 18. Gestire una risposta vuota in un JSONRequest con Volley
- 19. Risposta JSONArray con Volley per Android
- 20. Android Volley - BasicNetwork.performRequest: codice di risposta imprevisto 400
- 21. Con iron-ajax, come leggere le intestazioni di una risposta?
- 22. Errore server Volley con null Risposta di rete
- 23. Intestazione risposta da AVPlayer
- 24. Analizza manualmente parte di una risposta quando si utilizza Retrofit
- 25. Lettura di intestazioni di risposta quando si utilizza $ http di Angularjs
- 26. Come posso aggiungere intestazioni a una risposta da scintilla, quando si utilizza un trasformatore
- 27. Il browser non segue il reindirizzamento da una risposta AJAX (la risposta generata da PHP utilizza l'autenticazione CAS)
- 28. Intestazioni SOAP diverse in richiesta/risposta utilizzando Contratti di messaggistica
- 29. Perché la codifica non è impostata in risposta da Tomcat? Come posso affrontarlo?
- 30. Apache Solr: impostazione delle intestazioni di risposta HTTP da solrconfig.xml per CORS
grazie aiutato. –
Uomo, mi hai salvato la giornata! Molte grazie! – Roman
questa è una domanda vecchia, ma se aiuta oggi, puoi unire entrambe le soluzioni in una sola. String jsonString = new String (response.data, HttpHeaderParser.parseCharset (response.headers, "UTF-8")); In questo modo è possibile impostare il set di caratteri predefinito se non esiste nessuno. – hmartinezd