JC23 JC23 - 3 months ago 12
JSON Question

How to handle JSON response of array or object with Volley and Adapter

If searching for 2 or more fields the JSON response is an array of data:

{
"query": {
"count": 2,
"created": "2016-08-22T16:57:40Z",
"lang": "en-US",
"results": {
"data": [{
.
.
.
}]
}
}
}


But when searching for only 1 field the JSON response is an object of data:

{
"query": {
"count": 1,
"created": "2016-08-22T17:03:53Z",
"lang": "en-US",
"results": {
"data": {
.
.
.
}
}
}
}


I have it working fine with an array of data. But when a single object is returned the screen is blank. The logcat gives me a typeMismatch error that I'm pretty certain is due to this line

JSONArray data = results.getJSONArray("data");


Can I use Volley to handle both types of responses? Don't know if I need to create another adapter or what? Read a couple of similar posts but they all dealt with Retrofit and GSON so not certain the answers are applicable. Thanks

Answer

You are creating a JSONArray, which is expecting to parse an array. That is why there is both a JSONObject and a JSONArray to handle the two cases. It will throw a JSONException if parsing fails.

Best Solution

First of all, if you have control over the API, simply make sure your JSON response returns a array of elements, regardless if there's none, 1, or many. That way the JSONArray parse never fails

Secondary Solution

Assuming you don't have control over the actual API, take advantage of Java's try..catch. JSONArray return a specific exception if item's parsing fails

try {
   //Test if the item is an array
   JSONArray data = results.getJSONArray("data");
   //Do your other logic
} catch (JSONException exc) {
  //Parsing failed, test as an object
  try {
  JSONObject data = results.getJSONObject("data");
  //Do your other logic
  catch (JSONException exc) {
      //Parsing failed,.. do your failsafe 
   }
  }
}

(Using the exception type from) https://developer.android.com/reference/org/json/JSONArray.html#JSONArray()

Is this a pain? Yes. That's why if you can just make it always return an array, it'd be nicer for you in the long run. Sometimes there's sadly no way around nested try..catch though to handle cases like this.

(Additional info on try/catch) https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html

Comments