Gson使用多种对象类型反序列化JSON数组

我有一些奇怪的JSON像:

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

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

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

我会假设“类型”字段在我的JSON中排在第一位。 有没有一种可行的方法来消除这种假设?

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

 public class NewsFeedItemTypeAdapterFactory implements TypeAdapterFactory { @Override @SuppressWarnings("unchecked") public  TypeAdapter create(Gson gson, TypeToken type) { if (!NewsFeedItem.class.isAssignableFrom(type.getRawType())) { return null; } TypeAdapter jsonElementAdapter = gson.getAdapter(JsonElement.class); TypeAdapter newsFeedArticleAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedArticle.class)); TypeAdapter newsFeedAdAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedAd.class)); return (TypeAdapter) new NewsFeedItemTypeAdapter(jsonElementAdapter, newsFeedArticleAdapter, newsFeedAdAdapter).nullSafe(); } private static class NewsFeedItemTypeAdapter extends TypeAdapter { private final TypeAdapter jsonElementAdapter; private final TypeAdapter newsFeedArticleAdapter; private final TypeAdapter newsFeedAdAdapter; NewsFeedItemTypeAdapter(TypeAdapter jsonElementAdapter, TypeAdapter newsFeedArticleAdapter, TypeAdapter 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();