How to parse JSON response (different object types

2019-02-26 21:35发布

问题:

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).

回答1:

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.