Unlikely Legends Media Unlikely Legends Media - 3 months ago 14
Java Question

How to Parse REST API with three possible variations in Android

I am trying to parse a REST API that has 3 possible variations. The first one is the one I already have working where there is an array for the "row" output as shown in the photo below.

enter image description here

There is also row as an object, as pictured below.

enter image description here

And finally, one where there is no data, as shown below.
enter image description here

Any one of these is a possible output when parsing the API, I need something like an if statement to see which one is the output and parse the information from there, but I do not know how to create an if statement for this particular need. Here is my current code:

JSONObject parentObject = new JSONObject(finalJson);

JSONObject responseJSON = JSONUtils.jsonObjectFromJSONForKey(parentObject, "response");
if (responseJSON != null) {
JSONObject resultJSON = JSONUtils.jsonObjectFromJSONForKey(responseJSON, "result");
JSONObject contactsJSON = JSONUtils.jsonObjectFromJSONForKey(resultJSON, "Potentials");
JSONArray parentArray = contactsJSON.getJSONArray("row");


List<Photoshoots> photoshootsList = new ArrayList<>();
for (int i = 0; i < parentArray.length(); i++) {
JSONObject mainObject = parentArray.getJSONObject(i);
JSONArray mainArray = mainObject.getJSONArray("FL");
Photoshoots photoshoot = new Photoshoots();

...

Answer

I have solved the problem I was having. It may not be the ideal way to solve the problem, but it does work. Inside of the doInBackground in AsyncTask, I had initially converted the JSON result data into a StringBuffer, then converted the StringBuffer to a String. I then used one if and 2 else if statements to parse the data. The first if statement checks if the JSON string contains the phrase "nodata" representing that no data matches my original criteria, shown below:

if (finalJson.contains("nodata"))

I then had it pass on null data to be checked in onPostExecute for later. Next else if statement checked to see if row is an array. The way I did that was check to see if the string had a [ after row, indicating that it was an array, shown below:

else if (finalJson.contains("{\"response\":{\"result\":{\"Potentials\":{\"row\":["))

I then parsed the information as follows:

JSONArray parentArray = contactsJSON.getJSONArray("row");


                        for (int i = 0; i < parentArray.length(); i++) {
                            JSONObject mainObject = parentArray.getJSONObject(i);
                            JSONArray mainArray = mainObject.getJSONArray("FL");

the final else if, which could probably just be an else statement, is almost the same, except looking for a { after row instead of [, indicating it was just an object, as shown below:

else if (finalJson.contains("{\"response\":{\"result\":{\"Potentials\":{\"row\":{"))

I then parsed the information as follows:

JSONObject mainObject = contactsJSON.getJSONObject("row");
                            JSONArray mainArray = mainObject.getJSONArray("FL");

Inside of the onPostExecute, I have a code that will run a class that extends ArrayAdapter for the results contained in both of the else if statements, but I don't want it to run if there is no data, so I did the following:

    protected void onPostExecute(List<Photoshoots> result) {
                super.onPostExecute(result);



                if (result != null) {
    PhotoshootAdapter adapter = new PhotoshootAdapter(getApplicationContext(), R.layout.row, result);
                    lvPhotoshoots.setAdapter(adapter);}

else{
    new CountDownTimer(60000, 1000) {

                        public void onTick(long millisUntilFinished) {
                            btnRefresh.setText("No Data to Show. Try again in " + millisUntilFinished / 1000 + " Seconds");
                        }

                        public void onFinish() {
                            btnRefresh.setText("Refresh");
                            btnRefresh.setEnabled(true);
                        }
                    }.start();

The result will pass the null data if there is nodata, but a list if there is data within the result. Like I said, there may be a better way to solve this problem, but the app works now and it doesn't crash regardless of the data that is returned.