我有一些奇怪的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 <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();