我想使用jackson动态地将对象反序列化到适当的java类中,但我在正确配置jackson时遇到了问题。
我有以下简化模型(为了简洁起见省略了getter/setter):
class GeneralObject {
public String objType;
public String commonProp;
public GeneralObject nestedObject;
// map for additional properties, so that I can re-serialize the full object later
public Map<String, JsonNode> additionalFields = new HashMap<>();
@JsonAnyGetter
public Map<String, JsonNode> getAdditionalFields() {
return additionalFields;
}
@JsonAnySetter
public void addAdditionalField(String fieldName, JsonNode value) {
this.additionalFields.put(fieldName, value);
}
}
class SpecialObject extends GeneralObject {
public String specialProp;
}
事实上,有不同种类的“特殊对象”,我希望将来需要时能够添加更多。
JSON看起来是这样的(我从外部来源获得它们,我无法更改它们的发送格式):
{
"objType": "someType1",
"commonProp": "example1..."
}
{
"objType": "SPECIAL",
"commonProp": "example2...",
"specialProp": "more example"
}
{
"objType": "someOtherType",
"commonProp": "example3...",
"nestedObject": {
"objType": "SPECIAL",
"commonProp": "example2...",
"specialProp": "more example"
}
}
我目前正在像这样解析它们:
ObjectMapper mapper = new ObjectMapper();
String objString = "{\"objType\": \"SPECIAL\", \"commonProp\": \"...\", \"specialProp\": \"more example\"}";
GeneralObject genObj = mapper.readValue(objString, GeneralObject.class);
if (genObj.objType.equals("SPECIAL")) {
genObj = mapper.readValue(objString, SpecialObject.class);
}
// Some business-logic: If SPECIAL, then this cast is required to work:
System.out.println(((SpecialObject) genObj).specialProp);
这适用于顶级对象,但不适用于嵌套对象。例如,如果嵌套对象是特殊对象,它仍将作为公共对象反序列化。
我想做的是告诉jackson:“无论嵌套级别如何,如果objtype=special,请使用specialobject,否则请使用generalobject”。我研究了多态反序列化并尝试使用@jsonsubtypes,但无法正确设置此逻辑。如何确保特殊对象被反序列化到适当的类中,即使它们是嵌套的?
1条答案
按热度按时间htzpubme1#
我首先从这个要点中获得灵感,并尝试用一种习惯来解决它
TypeIdResolver
. 不幸的是,这存在无法反序列化objType
正确(参见本答案的第一版)。然后,我从这个答案中得到了灵感,转而选择了一种习惯
Deserializer
:它检查文件的内容
.objType
并发出应用于反序列化的适当(子)类。需要在服务器上注册反序列化程序GeneralObject
,例如,通过使用以下注解:为了阻止无限递归循环的发生,必须对所有子类进行注解,以避免使用此自定义反序列化器,并且我们需要引入一个帮助器类来停止
GeneralObject
:反序列化按预期工作,也适用于嵌套对象: