GSON - How can I parse two JSONArrays with the same name, but different parameters?

Brendan Wade Mahoney :

In the Reddit JSON API, comments can contain two different types of JSONArrays, both called "children".

"children" is usually an array of Objects containing a String "kind" and Object "data":

"children": [ { "kind": "t3", "data": {} } ...]

I've been handling these fine. My problem is that, sometimes, children will be a simple String array:

"children": [ "e78i3mq", "e78hees", "e78jq6q" ]

When parsing these, GSON throws an exception like the following:

Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 3780 path $[1].data.children[0].data.replies.data.children[0].data.replies.data.children[0].data.replies.data.children[0].data.children[0]

How can I handle these String array cases?

Brendan Wade Mahoney :

Sorry for the late answer, thanks for leading me in the right direction Emre!

I ended up getting GsonBuilder to work with a custom method, getGsonAdaptedData.

After retrieving the JSON response in a background thread:

...
Gson gson = new GsonBuilder().registerTypeAdapter(Data.class, (JsonDeserializer<Data>) (arg0, arg1, arg2) -> {
        JsonObject dataJsonObject = arg0.getAsJsonObject();
        Data data = new Gson().fromJson(dataJsonObject, Data.class);
        return RedditUtils.getGsonAdaptedData(dataJsonObject.get("children").getAsJsonArray(), data);
    }).create();
    final Feed responseSubredditFeed = gson.fromJson(jsonString, Feed.class);
...

RedditUtils.getGsonAdaptedData

// JSON returned for Reddit comments can contain two types of arrays named "children"
// This method checks to see if we were given a Children array or String array
// JSON member "replies" is similar, and can be found in the Data of some Children
// If the method finds a nested "children" array, it recursively adapts its Data
public static Data getGsonAdaptedData(JsonArray childrenJsonArray, Data data) {

    if (childrenJsonArray.size() > 0) {

        Gson gson = new Gson();

        if (childrenJsonArray.get(0).isJsonObject()) {

            data.setChildrenList(gson.fromJson(childrenJsonArray,
                    new TypeToken<List<Children>>() {
                    }.getType()));

            // Loops through every Data object in the array looking for children and replies
            for (int i = 0; i < childrenJsonArray.size(); i++) {

                JsonObject nestedDataJsonObject = childrenJsonArray.get(i).getAsJsonObject().get("data").getAsJsonObject();

                if (nestedDataJsonObject.has("children")) {
                    getGsonAdaptedData(nestedDataJsonObject.get("children").getAsJsonArray(), data.getChildren().get(i).getData());

                } else if (nestedDataJsonObject.has("replies") && nestedDataJsonObject.get("replies").isJsonObject()) {

                    data.getChildren().get(i).getData().setRepliesObject(gson.fromJson(nestedDataJsonObject.get("replies"),
                            new TypeToken<Replies>() {
                            }.getType()));

                    getGsonAdaptedData(nestedDataJsonObject.get("replies").getAsJsonObject().get("data").getAsJsonObject().get("children").getAsJsonArray(), data.getChildren().get(i).getData());
                }
            }
        } else {

            data.setRepliesList(gson.fromJson(childrenJsonArray,
                    new TypeToken<List<String>>() {
                    }.getType()));
        }
    }

    return data;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=103887&siteId=1