Eric Cochran Eric Cochran - 1 year ago 202
Java Question

Gson deserialize JSON array with multiple object types

I have some odd JSON like:

"value":"my string"
"value": {

Based on some field, the object in the array is a certain type.
Using Gson, my thought is to have a TypeAdapterFactory that sends delegate adapters for those certain types to a TypeAdapter, but I'm hung up on understanding a good way of reading that "type" field to know which type to create.
In the TypeAdapter,

Object read(JsonReader in) throws IOException {
String type = in.nextString();
switch (type) {
// delegate to creating certain types.

would assume the "type" field comes first in my JSON. Is there a decent way to remove that assumption?

Answer Source

Here is some code I wrote to handle an array of NewsFeedArticle and NewsFeedAd items in Json. Both items implement a marker interface NewsFeedItem to allow me to easily check if the TypeAdater should be used for a particular field.

public class NewsFeedItemTypeAdapterFactory implements TypeAdapterFactory {

    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if (!NewsFeedItem.class.isAssignableFrom(type.getRawType())) {
            return null;

        TypeAdapter<JsonElement> jsonElementAdapter = gson.getAdapter(JsonElement.class);
        TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedArticle.class));
        TypeAdapter<NewsFeedAd> newsFeedAdAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedAd.class));

        return (TypeAdapter<T>) new NewsFeedItemTypeAdapter(jsonElementAdapter, newsFeedArticleAdapter, newsFeedAdAdapter).nullSafe();

    private static class NewsFeedItemTypeAdapter extends TypeAdapter<NewsFeedItem> {

        private final TypeAdapter<JsonElement> jsonElementAdapter;
        private final TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter;
        private final TypeAdapter<NewsFeedAd> newsFeedAdAdapter;

        NewsFeedItemTypeAdapter(TypeAdapter<JsonElement> jsonElementAdapter,
                TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter,
                TypeAdapter<NewsFeedAd> newsFeedAdAdapter) {
            this.jsonElementAdapter = jsonElementAdapter;
            this.newsFeedArticleAdapter = newsFeedArticleAdapter;
            this.newsFeedAdAdapter = newsFeedAdAdapter;

        public void write(JsonWriter out, NewsFeedItem value) throws IOException {
            if (value.getClass().isAssignableFrom(NewsFeedArticle.class)) {
                newsFeedArticleAdapter.write(out, (NewsFeedArticle) value);

            } else if (value.getClass().isAssignableFrom(NewsFeedAd.class)) {
                newsFeedAdAdapter.write(out, (NewsFeedAd) value);



        public NewsFeedItem read(JsonReader in) throws IOException {
            JsonObject objectJson =;

            if (objectJson.has("Title")) {
                return newsFeedArticleAdapter.fromJsonTree(objectJson);

            } else if (objectJson.has("CampaignName")) {
                return newsFeedAdAdapter.fromJsonTree(objectJson);

            return null;

You can then register this with Gson using the following code.

return new GsonBuilder()
        .registerTypeAdapterFactory(new NewsFeedItemTypeAdapterFactory())
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download