我有一个看起来如下的课程
class Person {
Long id;
String firstName;
int age;
}
我的输入看起来像这样:
{ "id": null, "firstName": "John", "age": 10 }
或者像这样:
{ "id": 123 }
第一个变体代表一个“新”(非持久)人,第二个变量代表一个人的数据库ID。
如果id
非空,我想在反序列化期间从数据库加载对象,否则回退到常规解析并将其反序列化为新对象。
我尝试了什么:我目前有一个JsonDeserializer
用于数据库反序列化,但据我所知,没有办法“退回”常规解析。根据{{3}},我应该使用TypeAdapterFactory
和this answer。我对这种方法的问题是我给了JsonReader
(而不是例如JsonElement
)因此我无法确定输入是否包含有效id
而没有消耗输入。
有关如何解决此问题的任何建议?
答案 0 :(得分:0)
我不知道我是否正确理解了您的问题,但如果您已经有JsonDeserializer
,那么您应该有一个像这样的方法:
public Person deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { ... }
在此方法中,您拥有类型为context
的对象JsonDeserializationContext
,它允许您对指定对象调用默认反序列化。
所以,你可以在自定义反序列化器中做一些事情:
//If id is null...
Person person = context.deserialize(json, Person.class);
答案 1 :(得分:0)
我想我已经在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);
}
};
}
}
我还没有完全测试过,如果需要,我会回来修改它。 (现在发布它以开放反馈方法。)