简体   繁体   中英

How do I parse a field from a deep nested json object using Gson and retrofit in android?

I have a unique situation where I have to get certain times from a json's deeply nested object. It's a little complex, I couldn't find a solution so looking for ideas and ways to tackle this

I have a the json as follows:

[{
        "mySpaceId": 73220,
        "myBuildingId": 14019,
        "myFloorId": 10569,
        "myFloorNumber": "4",
        "myFloorName": "4th Floor",
        "spaceName": "My Room 4",
        "capacity": 5,
        "type": "huddle",
        "busyAt": []
    },
    {
        "mySpaceId": 73219,
        "myBuildingId": 14019,
        "myFloorId": 10569,
        "myFloorNumber": "4",
        "myFloorName": "4th Floor",
        "spaceName": "My room 5",
        "description": null,
        "capacity": 4,
        "type": "huddle",
        "timeZone": "America/New_York",

        "busyAt": [{
            "from": "2019-06-07T23:00:00+0000",
            "to": "2019-06-07T23:15:00+0000",
            "events": [{
                "id": "109142028",
                "series_id": null,
                "recurrence_id": null,
                "uid": "ABCDE",
                "space_id": 73219,
                "start": {
                    "date_time": "2019-06-07T19:00:00-0400",
                    "time_zone": "America/New_York"
                },
                "end": {
                    "date_time": "2019-06-07T19:15:00-0400",
                    "time_zone": "America/New_York"
                },
                "started_at": "2019-06-07T19:00:00-0400",
                "ended_at": "2019-06-07T19:15:00-0400"
            }]
        }]
    }
]

I use this : http://www.jsonschema2pojo.org/ to generate a class from the above json string. I was wondering how do I retrieve the "started_at": "2019-06-07T19:00:00-0400",

from busyAt-> events into my main model class generated by the above site? Say at the same level as mySpaceId. I currently use the following :

 public List<BusyAt> getBusyAt() {
        return busyAt;
    }

    public void setBusyAt(List<BusyAt> busyAt) {
        this.busyAt = busyAt;
    }

Is there a way I can retrieve the started_at at this level and parse the date and time in the format : 8:00 am ? to use it in my code.

Any idea how to go about this? Thanks! Please let me know if this is confusing or need more clarification, happy to post more code.

You will have to do something like this :

JSONArray array = new JSONArray(result);
for (int i = 0; i < array.length(); ++i) {
JSONObject jObj = array.getJSONObject(i);

String busyAt = jObj.getString("busyAt");
// convert it to json array 
JSONArray busyAtArray = new JSONArray(busyAt)
String endedAt = busyAtArray.getJSONObject(0).getString("ended_at")
// convert the string and get the time from it

}

I hope you got the general idea from this. This snippet can certainly be written in a better way.

You can use google GSON for parsing this JSON. Here's the link for google GSON is [https://search.maven.org/artifact/com.google.code.gson/gson/2.8.5/jar] .

That would be a better alternative than creating classes. Just click on the Downloads section on the right side of the page (the page resulting from the above link) and download the Jar file and the sources file too if you would like to debug using the actual source. Finally, include these in your project.

As far as the code is concerned, here is a snippet from what I have written:

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.File;
import java.io.FileReader;
import java.util.logging.Logger;

public class JSONTester {

    private static File json = new File("/Users/XXXX/Production/StackOverFlow/JSON_From_https-::stackoverflow.com:questions:56501897:how-do-i-retrieve-json-from-a-deep-nested-object#56501897.json");
    private static Logger jsonLogger = Logger.getLogger(JSONTester.class.getSimpleName());


    public static void main(String[] args) {
        JsonElement jsonElement;
        try {
            jsonElement = new JsonParser().parse(new FileReader(json));
        } catch (Exception e) {
            jsonLogger.severe("There was an error parsing the JSON with message " + e.getLocalizedMessage());
            return;
        }

        if (jsonElement != null) {
            if (jsonElement instanceof JsonArray) {
                JsonArray jsonArray = (JsonArray) jsonElement;
                for (int i = 1; i < jsonArray.size(); i++) {
                    JsonElement element = jsonArray.get(i);
                    //We are considering only JSON objects inside a JSONArray.
                    if (element instanceof JsonObject) {
                        JsonObject jsonObject = (JsonObject) element;
                        if (jsonObject.has("busyAt")) {
                            JsonArray busyAtJsonArray =
                                    jsonObject.getAsJsonArray("busyAt");
                            if (busyAtJsonArray != null && busyAtJsonArray.size() >
                                    0) {
                                //You got the busyAt json array. Now, since you already know
                                //that events is another JSONArray within busyAt array, process this
                                //array accordingly. Get the first JsonObject from the events
                                //array to get "started_at" and "ended_at" fields from
                                //this (first) json object.
                                                                    //busyAt.get(0) = from,to,events[],
                                JsonObject firstJsonObject = (JsonObject) busyAtJsonArray.get(0);
                                JsonArray eventsArray = firstJsonObject.getAsJsonArray("events");
                                JsonObject eventsFirstObject = (JsonObject) eventsArray.get(0);
                                String started_At = eventsFirstObject.get("started_at").getAsString();
                                String ended_At = eventsFirstObject.get("ended_at").getAsString(); 

                            }
                        }
                    }
                }
            }
        }
    }
} 

Please note that I have been careful in assuming whether a JsonElement is a JsonArray or JsonObject. You should also try doing that so that when you encounter any exceptions, you will know what caused it. Obviously, you will get class cast exceptions (or others depending on what you were doing wrong), but it is a good idea to keep a track of why it happened.

For more details, go through the GSON library documentation (link https://sites.google.com/site/gson/gson-user-guide ) and how to parse Json objects, Json Arrays etc. This will clearly explain the benefits of using GSON and its advantages over other methods of JSON parsing. The basic element you get when you parse either one of these will be JsonElement. You can then cast it to either of the above depending on what you think is the right element there (json object or array). Or, if you are well-versed with the JSON structure, you can just cast it and get the results accordingly.

I use this : http://www.jsonschema2pojo.org/ to generate a class from the above json string. I was wondering how do I retrieve the "started_at": "2019-06-07T19:00:00-0400", from busyAt-> events into my main model class generated by the above site? Say at the same level as mySpaceId. I currently use the following :

If I interpret you correctly, you have created using the www.jsonschema2pojo.org the following classes: -

  • a class called "Entity" that contains "mySpaceId" and a list of "BusyAt".
  • class "BusyAt" contains a list of "Event".
  • class "Event" contain a String called StartedAt.

I assume that you want to retrieve the First entry of each list (if it exist) directly from the top-most class ("Entity")

something like: -

entity.busyAt(0).events(0).startedAt
if either busyAt or event list is empty or null, then return empty string for startedAt.

what you can do, is to create the following method in the "Entity" class (root class containing both mySpaceId, and List).

public String getStartedAt(){
  //check if the busyAt List contains items or not.
  if (busyAt ==null || busyAt.isEmpty()){
    return "";
  }
  //take the list of events from the first busyAt in the array
  List<Event> eventList = busyAt.get(0).getEvents();
  //check if the event List contains items or not.
  if (eventList ==null || eventList.isEmpty()){
    return "";
  }
  //return the StartAt value of the first event.
  return eventList.get(0).getStartedAt(); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM