How to parse JSON response (different object types) with GSON

12,612

This is correct because the object you are trying to access is not an array, you should do something like this:

JsonParser parser = new JsonParser();
JsonObject data = parser.parse(response).getAsJsonObject();
Meta meta = gson.fromJson(data.get("meta"), Meta.class);
Response myResponse = gson.fromJson(data.get("response"), Response.class);

Or you can create an object containing 3 classes for the 3 objects and then parse everything through GSON.

Share:
12,612
cavega
Author by

cavega

Updated on July 23, 2022

Comments

  • cavega
    cavega almost 2 years

    Problem: parse the following response from Foursquare Venues API:

    {
        meta: {
            code: 200
        }
        notifications: [
        {
            type: "notificationTray"
            item: {
            unreadCount: 0
            }
        }
        ]
        response: {
            venues: [
            {
                id: "5374fa22498e33ddadb073b3"
                name: "venue 1"
            },
            {
                id: "5374fa22498e33ddadb073b4"
                name: "venue 2"
            }
            ],
            neighborhoods: [ ],
            confident: true
        }
    }
    

    The GSON documentation website recommends using GSON's parse API to parse the response as a JSONArray and then read each array item into an appropriate Object or data type (Example here). As such, I originally switched to the following implementation:

    JsonParser parser = new JsonParser();
                    try {
                        JSONObject json = new JSONObject(response);
                        JSONArray venues = json.getJSONObject("response").getJSONArray("venues");
    
                        int arraylengh = venues.length();
                        for(int i=0; i < arraylengh; i++){
                            Log.d(TAG, "The current element is: " + venues.get(i).toString());
                        }
                    }
                    catch(JSONException e){
    
                    }
    

    The code above gave me a JSONArray with all the "venues". The next problem was that I do not know how to parse/convert the "venues" JSONArray into a ArrayList (for my custom Venue object).

    Solution: As outlined on JohnUopini answer I was able to successfully parse the JSON by using the following implementation:

    GsonBuilder gsonBuilder = new GsonBuilder();
    Gson gson = gsonBuilder.create();
    
    JsonParser parser = new JsonParser();
    JsonObject data = parser.parse(response).getAsJsonObject();
    Meta meta = gson.fromJson(data.get("meta"), Meta.class);
    Response myResponse = gson.fromJson(data.get("response"), Response.class);
    List<Venue> venues = Arrays.asList(myResponse.getVenues());
    

    With the above code I was able to successfully parse the "meta" as well as the "response" JSON properties into my custom objects.

    For reference, below is my Response class (NOTE: The properties were defined as public for testing purposes. A final implementation should have these declared as private and use setters/getters for encapsulation):

    public class Response {
    
        @SerializedName("venues")
        public Venue[] venues;
    
        @SerializedName("confident")
        public boolean confident;
    
        Response(){}
    }
    

    Note/Feedback: After implementing the accepted answer's recommendation, a couple of times I encountered the following (or similar) exception message during my debugging process:

    com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT
    

    The reason I was getting the above exception was because the "type" on some of the children inside the "venues" JSON did not match with the "type" I defined such objects in my custom Venue class. Make sure the type in your custom Classes has a 1-to-1 correspondence with the JSON (i.e. [ ] is a array property, { } is an Object property, etc).

  • cavega
    cavega almost 10 years
    I was able to parse the Meta object after I refactored your statement to use data.get("meta"). However, I'm getting an exception (com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT)for my custom Response object when I tried the following: <mypackage>.Response myResponse = gson.fromJson(data.get("response"), <mypackage>.Response.class);
  • JohnUopini
    JohnUopini almost 10 years
    Check your response class, venues is an array of objects probably you just have a String there
  • cavega
    cavega almost 10 years
    I updated post with my Response class. I made it an Array (as opposed to a List<Venue>) because of the square brackets in the JSON. Maybe the problem is with one of the child of the Venue array.
  • cavega
    cavega almost 10 years
    By commenting out some of the properties in my Response class I was able to debug the offending ones that were defined incorrectly (i.e. Object vs Array) and successfully parse the JSOn. Thanks for your answer!