【问题标题】:Gson deserialize JSON array with multiple object typesGson 反序列化具有多种对象类型的 JSON 数组
【发布时间】:2016-04-21 21:32:36
【问题描述】:

我有一些奇怪的 JSON,例如:

[
  {
    "type":"0",
    "value":"my string"
  },
  {
    "type":"1",
    "value":42
  },
  {
    "type":"2",
    "value": {
    }
  }
]

基于某个字段,数组中的对象是某种类型。 使用 Gson,我的想法是拥有一个 TypeAdapterFactory,它将这些特定类型的委托适配器发送到 TypeAdapter,但我很想了解一种阅读“类型”字段以了解要创建哪种类型的好方法。 在 TypeAdapter 中,

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

假设“类型”字段首先出现在我的 JSON 中。有没有一种体面的方法可以消除这种假设?

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    这是我编写的一些代码,用于处理 Json 中的一组 NewsFeedArticle 和 NewsFeedAd 项目。这两个项目都实现了一个标记接口 NewsFeedItem,让我可以轻松地检查 TypeAdater 是否应该用于特定字段。

    public class NewsFeedItemTypeAdapterFactory implements TypeAdapterFactory {
    
        @Override
        @SuppressWarnings("unchecked")
        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;
            }
    
            @Override
            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);
    
                }
    
            }
    
            @Override
            public NewsFeedItem read(JsonReader in) throws IOException {
                JsonObject objectJson = jsonElementAdapter.read(in).getAsJsonObject();
    
                if (objectJson.has("Title")) {
                    return newsFeedArticleAdapter.fromJsonTree(objectJson);
    
                } else if (objectJson.has("CampaignName")) {
                    return newsFeedAdAdapter.fromJsonTree(objectJson);
                }
    
                return null;
            }
        }
    }
    

    然后您可以使用以下代码向 Gson 注册它。

    return new GsonBuilder()
            .registerTypeAdapterFactory(new NewsFeedItemTypeAdapterFactory())
            .create();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-31
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多