Gson:如果存在某些字段,则自定义反序列化
Posted
技术标签:
【中文标题】Gson:如果存在某些字段,则自定义反序列化【英文标题】:Gson: Custom deserialization if certain field is present 【发布时间】:2013-09-03 06:14:54 【问题描述】:我有一个如下所示的类
class Person
Long id;
String firstName;
int age;
我的输入看起来像这样:
"id": null, "firstName": "John", "age": 10
或者像这样:
"id": 123
第一个变体代表一个“新”(非持久化)人,第二个变体通过数据库 id 指代一个人。
如果id
不为空,我想在反序列化期间从数据库中加载对象,否则会退回到常规解析并将其反序列化为新对象。
我的尝试:我目前有一个 JsonDeserializer
用于数据库反序列化,但据我了解,没有办法“退回”常规解析。根据this answer,我应该使用TypeAdapterFactory
和getDelegateAdapter
。这种方法的问题是我得到了一个JsonReader
(而不是例如JsonElement
),所以我无法确定输入是否包含有效的id
而不消耗输入。
关于如何解决这个问题的任何建议?
【问题讨论】:
【参考方案1】:我不知道我是否正确理解了你的问题,但如果你已经有一个JsonDeserializer
,你应该有一个像这样的方法:
public Person deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) ...
在此方法中,您拥有JsonDeserializationContext
类型的对象context
,它允许您对指定对象调用默认反序列化。
因此,您可以在自定义反序列化器中执行类似操作:
//If id is null...
Person person = context.deserialize(json, Person.class);
见JsonDeserializationContext
documentation。
【讨论】:
我尝试过这个,但由于无休止的递归,我得到了 ***Exception。我认为上下文代表“这个”gson,而不是没有这个类型适配器的这个gson。 @aioobe: 在JsonDeserializer
中创建一个新的Gson
对象并执行Person person = new Gson().fromJson(json, Person.class);
怎么样?
对,这对于我在我的问题中写的简单示例来说是可行的。但是,在我的实际代码中,我引用了其他对象(例如,假设 Person
将引用 Person parent
)。如果我们将一个人的解析委托给另一个 gson
对象,则无法从数据库中加载 parent。【参考方案2】:
我想我在here 上的答案的帮助下设法解决了这个问题。
这是一个工作类型的适配器工厂:
new TypeAdapterFactory()
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type)
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter =
gson.getAdapter(JsonElement.class);
// Are we asked to parse a person?
if (!type.getType().equals(Person.class))
return null;
return new TypeAdapter<T>()
@Override
public T read(JsonReader reader) throws IOException
JsonElement tree = elementAdapter.read(reader);
JsonElement id = tree.getAsJsonObject().get("id");
if (id == null)
return delegate.fromJsonTree(tree);
return (T) findObj(id.getAsLong());
@Override
public void write(JsonWriter writer, T obj) throws IOException
delegate.write(writer, obj);
;
我还没有完全测试它,如果需要我会回来修改它。 (现在发布它以开放以获取有关该方法的反馈。)
【讨论】:
以上是关于Gson:如果存在某些字段,则自定义反序列化的主要内容,如果未能解决你的问题,请参考以下文章
如何反序列化包含 GSON 库生成的 LocalDate 字段的 JSON