2

I need to parse a JSON response regarding events in an agenda, of which a field is dynamic. This field changes depending on the month in which the event takes place.

Now I've been parsing data with GSON before, but these all had static fields so it was quite easy to create the necessary POJO's. But how would I do this with dynamic fields?

The response i need to parse is like so:

{
  "Agenda/Future": {
    "November 2011/0": [
      {
        "id": "5675",
        "eventid": "",
        "name": "testing testing 123",
        "startdate": "nov 25",
        "datecompute": "2011-11-25T08:00:00",
        "group_month": "November 2011",
        "flg_Data": "Database"
      }
    ],
    "February 2012/1": [
      {
        "id": "5681",
        "eventid": "",
        "name": "dfd",
        "startdate": "feb 3",
        "datecompute": "2012-02-03T12:00:00",
        "group_month": "February 2012",
        "flg_Data": "Database"
      },
      {
        "id": "5679",
        "eventid": "",
        "name": "vfvd",
        "startdate": "feb 17",
        "datecompute": "2012-02-17T12:00:00",
        "group_month": "February 2012",
        "flg_Data": "Database"
      }
    ],
    "February 2013/2": [
      {
        "id": "5680",
        "eventid": "",
        "name": "df",
        "startdate": "feb 14",
        "datecompute": "2013-02-14T12:00:00",
        "group_month": "February 2013",
        "flg_Data": "Database"
      }
    ],
    "September 2013/3": [
      {
        "id": "5677",
        "eventid": "",
        "name": "fsdfsd",
        "startdate": "sep 14",
        "datecompute": "2013-09-14T12:00:00",
        "group_month": "September 2013",
        "flg_Data": "Database"
      }
    ],
    "November 2015/4": [
      {
        "id": "5676",
        "eventid": "",
        "name": "fsdfsd",
        "startdate": "nov 13",
        "datecompute": "2015-11-13T12:00:00",
        "group_month": "November 2015",
        "flg_Data": "Database"
      }
    ]
  }
}

As you can see, the object title regarding months is dynamic. Both the value at the end of the title, as well as the title itself change based on the actual month and position in the array of months.

From what I've seen on other questions here at SO, I will need to work with Maps. But I'm not quite sure how I would go about doing so. Let's say I create a POJO called Event for the individual events contained in the array of the months, what would my initialization look like?

Regards


I have tried Amir's suggestion by using Jackson with the default Map. Sadly, this creates a Map with a size of 1. The entire JSON response gets parsed into a single object. Ofcourse, this is not what I want, since I need to get the data from the individual events.

Does anyone have a suggestion as to how I might be able to do that? Normally I'd figure out these things quite quickly but I can't wrap my head around this one due to the dynamic object naming.


I have eventually managed to crack this problem. I ended up using plain JSONObjects, which worked eventually.

The code I used to get it to work is as follows:

        JSONObject jsonObject = new JSONObject(response);
        JSONObject agenda = jsonObject.getJSONObject("Agenda/Future");

        if (agenda != null) {
            System.out.println(agenda.length());
            JSONArray events = agenda.names();
            if (events.length() > 0) {
                System.out.println("At least its bigger then 0. It's: "
                        + events.length());
                for (int i = 0; i < events.length(); i++) {
                    System.out.println(events.get(i).toString());
                    JSONArray test = agenda.getJSONArray(events.get(i)
                            .toString());
                    if (test != null) {
                        JSONObject testt = test.getJSONObject(0);
                        if (testt != null) {
                            System.out.println(testt.getString("name"));
                        } else {
                            System.out.println("Still empty, Check again.");
                        }
                    }
                }
            }

        } else {
            System.out.println("Agenda is completely empty, try again.");
        }

As you can see, this still contains test-names, but at least it works. Thanks for the help everyone!

Sander van't Veer
  • 5,930
  • 5
  • 35
  • 50

2 Answers2

1

If all your fields, as you have said, are dynamic then you can create a super set of all fields in a pojo. But that doesn't really help and I think the Map is the best solution. With GSON, you can do

Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> map = gson.fromJson("{'key1':'123','key2':'456'}", type);

This will return a map of strings.

I haven't actually used GSON to do this before though. I have been very happy with Jackson lib and with that you can do

new ObjectMapper().readValue("...json...", Map.class)

The above will return a map of maps which is what you want.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • I might give Jackson a whirl for this, but if possible I'd rather use GSON since that's the one I currently have the most experience with. However your quick example uses 2 `Strings` in the `Map`, do you think it would work if I used something like: `Type type = new TypeToken>(){}.getType(); Map map = gson.fromJson(myJsonrResponse, type);` Like I said in my original post? – Sander van't Veer Nov 01 '11 at 14:49
  • With Jackson I know this will work because I have tried it. With GSON I think Map of events will work. But map of maps I am not sure of. – Amir Raminfar Nov 01 '11 at 15:45
  • I managed to finally crack my problem, but mjmarsh gave me the suggestion that ended up working. Thanks a lot though for mentioning Jackson, it does seem rather usefull so I'm sure I'll use it in the future – Sander van't Veer Nov 02 '11 at 14:11
  • No problem. A while back I noticed that the two best json libs are GSON and Jackson. I found that Jackson is A LOT faster. See these links http://www.cowtowncoder.com/blog/archives/2009/09/entry_326.html and http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking and http://stackoverflow.com/questions/2378402/jackson-vs-gson. Happy coding! – Amir Raminfar Nov 02 '11 at 17:00
1

Since the month data are not valid java identifiers, you 'll probably have to use custom serialization with GSON. You're talking about using Map objects but if you are going to do that you may as well us the org.json objects like JSONObject which are basically built on maps/hashtables anyway.

Mike Marshall
  • 7,788
  • 4
  • 39
  • 63
  • After first discarding this answer since Amir's aproach seemed the one I needed, I ended up trying out normal `JSONObject`s which eventually helped me crack my problem. So thanks a lot! Accepted – Sander van't Veer Nov 02 '11 at 14:13