I have a Volley JSONRequest that is getting stuck because the response from the server is not a valid JSON (it's html).
How is it possible to gracefully handle this error? I have this implementation:
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
… something …
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
Log.i(TAG,"error "+error.toString());
}
});
queue.add(jsObjRequest);
However when i send the request and get a not valid JSON response, the onErrorResponse doesn't get called. Instead i get an exception
08-14 16:26:15.590: D/538 - JsonRequest(27888): exception error Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
and the whole app crashes.
I managed to track that error to the following line in the JsonObjectRequest.java class:
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
Log.d(TAG,"response headers "+response.headers.toString());
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
Log.d(TAG,"json string "+jsonString);
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
Log.d(TAG,"parse error");
return Response.error(new ParseError(e));
} catch (JSONException je) {
Log.d(TAG,"exception error "+je.getLocalizedMessage());
return Response.error(new ParseError(je));
}
}
the line that gets called is : return Response.error(new ParseError(je));
How do i catch that so it doesn't crash the app?
Thanks in advance!
If you are expecting to get JSON, you should check that your URL is valid. HTML is often returned when the request is invalid. Such examples are when a request returns a 404 not found webpage.
If you are trying to get HTML (or XML), you can use a StringRequest
to get a String, then convert it to a XML Document
or can use a SAXParser
to parse it. For example:
StringRequest request = new StringRequest(Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
Document xml = factory.newDocumentBuilder().parse(response);
//TODO: handle XML Document parsing
} catch (Throwable t) {
return ;
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
queue.add(request);
One thing that you may wish to consider as a simpler alternative is my droidQuery library. To complete this request with droidQuery:
$.ajax(new AjaxOptions().url(url)
.type("GET")
.dataType("XML")
//optionally, add own SAX parser with SAXContentHandler or customXMLParser methods
.success(new Function() {
@Override
public void invoke($ droidQuery, Object... params) {
Document xml = (Document) params[0];
//TODO: parse Document
}
})
.error(new Function() {
@Override
public void invoke($ droidQuery, Object... params) {
AjaxError error = (AjaxError) params[0];
Log.e("$", "Error " + error.status + ": " + error.error);
}
}));