1

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.

3 Answers3

1

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.

user 007
  • 821
  • 10
  • 31
  • Angela - @user 007 is telling you to use Google's GSON library instead of the model classes that you are using. This is a different approach to parsing the JSON than the classes approach that you are using. I am in the middle of writing the same answer with a little more code. – Ashish Jun 07 '19 at 23:48
1

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.

Ashish
  • 209
  • 1
  • 10
  • is it not possible to call it from UI code as : modelobj.getBusyAt().get(0).getEvents().get(0).getStartedAt() –  Jun 08 '19 at 14:22
  • Yes, for sure. It is perfectly possible. But, what do you mean by UI code? JavaScript, you mean? You can try it out in the main method and see if it works. What is your preferred language of coding? This code is written in Java. Not sure where the UI component comes up here. – Ashish Jun 08 '19 at 15:21
  • By UI I meant in my UI classes. say I have an appdatamanger where I retrieve the response, like in here : https://pastebin.com/aabg65gX .response is the above json returned, I was wondering if there is a way I can get started_at time in the response (in my code) somehow ,say like : modelobj.getBusyAt().get(0).getEvents().get(0).getStartedAt() . (This doesnt seem to work though), looking for an easier way to retrieve started_at –  Jun 08 '19 at 15:44
  • I have added code to get the started_At and ended_At time strings. – Ashish Jun 08 '19 at 16:43
  • is there no easier way to do this without nesting code ? say in my class for pastebin example , i have added : for (int i = 0; i < response.size(); i++) { FreeSpace room = response.get(i); if (isRoomAvailable(room)) { returnedRooms.add(room); } ,something similar to return started_at? any ideas –  Jun 08 '19 at 17:57
  • something like this would be helpful : https://stackoverflow.com/questions/23070298/get-nested-json-object-with-gson-using-retrofit any ideas how to go bout it for my case –  Jun 08 '19 at 18:17
  • Hmm. Using the class approach is what you are saying you are looking for. Let me give it a try. I got the class format from [http://www.jsonschema2pojo.org/]. I'll use Jackson or GSON itself to de-serialize and see if it works out. – Ashish Jun 08 '19 at 19:59
  • I plan to use GSON and that'd be really helpful, thanks! I appreciate it –  Jun 08 '19 at 20:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/194646/discussion-between-ashish-and-angela-heely). – Ashish Jun 08 '19 at 21:32
0

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(); 
}
Angel Koh
  • 12,479
  • 7
  • 64
  • 91
  • thanks so much for your answer! Also, I am using : https://pastebin.com/Qa48XBzM this exact class as my model class after conversion to pojo. Where should I place the startedAt function in my code? Seems like I am getting an error " at List eventList = busyAt.get(0);" saying required List ,but found when I place that in my main/root class (freespace). –  Jun 09 '19 at 18:01
  • I just needed to add List eventList = busyAt, but it works like a charm! , thanks so much! –  Jun 09 '19 at 18:55
  • Hi Angel Koh, any idea about this :https://stackoverflow.com/questions/57598276/how-do-i-pass-a-multi-part-body-parameter-for-rxjava2-androidnetworking-post-req ( figured you are really good at JSON and probably have a good idea what I could be missing) –  Aug 21 '19 at 19:48