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

139
October 06, 2018, at 09:10 AM

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?

Answer 1

If the same endpoint is returning a different type in some instances I suggest wrapping that part in an object and using a deserializer to check the type and assign accordingly. You can do something like this:

public Parent serialize(String jsonString) {
    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(WrappedChild.class, new ChildDeserializer());
    Gson gson = builder.create();
    return gson.fromJson(jsonString, Parent.class);
}
class Parent {
    public List<WrappedChild> children;
}
class ObjectChild {
    public String body;
}
class WrappedChild {
    public ObjectChild objectChild;
    public String stringChild;
}
class ChildDeserializer implements JsonDeserializer<WrappedChild> {
    private Gson gson = new Gson();
    @Override
    public WrappedChild deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        if (json != null) {
            if (json.isJsonObject()) {
                WrappedChild result = new WrappedChild();
                result.objectChild = gson.fromJson(json, ObjectChild.class);
                return result;
            } else if (json.isJsonPrimitive()) {
                WrappedChild result = new WrappedChild();
                result.stringChild = json.getAsString();
                return result;
            }
        }
        return null; // Or throw new Exception("Unknown child type");
    }
}

If you are using retrofit just pass the Gson created by the builder to GsonConverterFactory.create as a parameter when creating your service.

Rent Charter Buses Company
READ ALSO
Downloading Images from Firebase Storage Faster

Downloading Images from Firebase Storage Faster

The current architecture structure that I have for my Firebase storage is as follow:

209
Android - Google signin issue with Oauth2

Android - Google signin issue with Oauth2

I encounter an error when implementing google signin on my application

245
Can&#39;t use android:background with button from the new material components

Can't use android:background with button from the new material components

I'm using the new material components comgoogle

128
kvm permission denied on Android Studio emulator

kvm permission denied on Android Studio emulator

When I try to run an AVD, I get this erros:

242