Gson反序列化具有多种对象类型的JSON数组 [英] Gson deserialize JSON array with multiple object types
问题描述
我有一些奇怪的JSON,例如:
[
{
type:0 ,
value:我的字符串
},
{
type:1,
value:42
},
{
type:2,
value:{
}
}
]
基于某些字段,数组中的对象是某种类型。
使用Gson,我的想法是有一个TypeAdapterFactory,它将这些特定类型的委托适配器发送给TypeAdapter,但是我很想理解一种阅读该type字段的好方法,以知道要创建哪种类型。
在TypeAdapter中,
Object read(JsonReader in)抛出IOException {
String type = in。 nextString();
switch(type){
//委托创建某些类型。
$ b $ p
$ b $ p $会假定type字段在我的第一位JSON。有没有一种体面的方式来消除这种假设?解决方案以下是我编写的用于处理NewsFeedArticle和NewsFeedAd项目数组的代码在Json。这两个项目都实现了一个标记接口NewsFeedItem,以便我轻松检查TypeAdater是否应该用于特定的字段。
public class NewsFeedItemTypeAdapterFactory实现TypeAdapterFactory {
$ b $ @覆盖
@SuppressWarnings(未选中)
public< T> TypeAdapter< T>创建(Gson gson,TypeToken< T>类型){
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;
$ b @Override
public void write(JsonWriter out,NewsFeedItem value)抛出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(在).getAsJsonObject();
if(objectJson.has(Title)){
return newsFeedArticleAdapter.fromJsonTree(objectJson);
} else if(objectJson.has(CampaignName)){
return newsFeedAdAdapter.fromJsonTree(objectJson);
}
返回null;
}
}
}
然后您可以注册Gson使用以下代码。
返回新的GsonBuilder()
.registerTypeAdapterFactory(new NewsFeedItemTypeAdapterFactory())
.create();
I have some odd JSON like:
[
{
"type":"0",
"value":"my string"
},
{
"type":"1",
"value":42
},
{
"type":"2",
"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?
解决方案 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 {
@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;
}
}
}
You can then register this with Gson using the following code.
return new GsonBuilder()
.registerTypeAdapterFactory(new NewsFeedItemTypeAdapterFactory())
.create();
这篇关于Gson反序列化具有多种对象类型的JSON数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!