mattu
mattu

Reputation: 1024

Volley Json Requests not working - String cannot be converted to JsonObject / JsonArray

I am working on an Android app and getting JsonObject/JsonArray from the server. Converting the String to Json manually works ok.
I recently switched to Volley for server requests, and want to use JsonObjectRequest / JsonArrayRequest (rather than just plain StringRequest) to get the json directly and not have to bother about converting the string first (that's what the Json Requests were made for, right?). However, the code always ends up in onErrorResponse with a ParseError saying that the String cannot be converted to a JsonObject / JsonArray (even though syntax seems totally ok). I have tried to eliminate potential "invisible" characters by converting the server response to UTF8 (as suggested here ) but doesn't appear to solve the problem either. Also, the iOS version does not seem to have any issues with the same responses (I know that the underlying parsing algorithm may be very different).

Of course, working with StringRequests or making custom requests would do the job (as suggested in a few other stackoverflow discussions), but it just bugs me a lot that I cannot get Json Requests to work. Anyone had this problem as well? Would be great to hear about potential causes and solutions!

Upvotes: 2

Views: 892

Answers (1)

mattu
mattu

Reputation: 1024

Ok, I found the answer. The JsonObjectRequest / JsonArrayRequest take an additional JsonObject / JsonArray object as an argument. In most sample codes online, this argument is set to null and I did the same because I did not want to send a Json, only to receive. Now what happens (quite unintuitively) behind the scenes of the Volley Json requests, is that if this argument is null the request is not done as a POST request, but as a GET instead. This caused my request to fail and the server to return an error code rather than a json. Such an error code in turn could not be parsed to a json of course. Very bad choice for a default implementation in Volley I find.

In any case, the solution was as easy as introducing a CustomJsonObjectRequest which is very similar to the implementation from the library, except that it sticks with the POST request:

public class CustomJsonObjectRequest extends Request<JSONObject> {

protected static final String PROTOCOL_CHARSET = "utf-8";

private final Response.Listener<JSONObject> mListener;

public CustomJsonObjectRequest(String url, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
    super(Method.POST, url, errorListener);
    mListener = listener;
}

@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
    try {
        String jsonString = new String(response.data,
                HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
        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));
    }
  }

  @Override
  protected void deliverResponse(JSONObject response) {
    mListener.onResponse(response);
  }

}

Upvotes: 1

Related Questions