大佬教程收集整理的这篇文章主要介绍了具有“默认”对象类型的嵌套对象的动态反序列化,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我想使用 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;
}
实际上,有各种各样的“特殊对象”,我想成为 将来需要时可以添加更多。
Jsons 看起来像这样(我从外部来源获取它们,我无法更改 发送的格式):
{
"objType": "someType1","commonProp": "example1..."
}
{
"objType": "SPECIAL","commonProp": "example2...","specialProp": "more example"
}
{
"objType": "someOtherType","commonProp": "example3...","nestedobject": {
"objType": "SPECIAL","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:
Sy@R_502_6563@.out.println(((SpecialObject) genObj).specialProp);
这适用于顶级对象,但不适用于嵌套对象。如果,对于 例如,嵌套对象是一个特殊对象,它仍然会被反序列化为 一个共同的对象。
我想要做的是告诉 Jackson:“无论嵌套级别如何,如果 objType=SPECIAL,则使用 SpecialObject,否则使用 GeneralObject”。我查看了 Polymorphic Deserialization 并尝试使用 @JsonSubTypes,但无法正确设置此逻辑。我如何确保将 SPECIAL 对象反序列化为适当的类,即使它们是嵌套的?
我首先从 this Gist 中获得灵感,并尝试使用自定义 TypEIDResolver
解决它。不幸的是,这存在无法正确反序列化 objType
的问题(请参阅此答案的第一个版本)。
然后我从 this answer 获得灵感并切换到自定义 Deserializer
:
class CustomDeserializer extends StdDeserializer<GeneralObject> {
private static final String SPECIAL = "\"SPECIAL\"";
protected CustomDeserializer() {
super(GeneralObject.class);
}
@Override
public GeneralObject deserialize(JsonParser p,DeserializationContext ctX) throws IOException {
TreeNode node = p.readValueAsTree();
// SELEct appropriate class based on "resourceType"
TreeNode objTypeNode = node.get("objType");
if (null == objTypeNodE) {
throw new JsonParseException(p,"field \"objType\" is missing!");
}
if (!objTypeNode.isValueNode()) {
throw new JsonParseException(p,"field \"objType\" must be a String.");
}
String objType = objTypeNode.toString();
Class<? extends GeneralObject> clazz;
if (objType.equals(SPECIAL)) {
clazz = SpecialObject.class;
} else {
clazz = RecursionStopper.class;
}
return p.getCodec().treeToValue(node,clazz);
}
}
它检查 .objType
的内容并发出应该用于反序列化的适当(子)类。解串器需要在 GeneralObject
上注册,例如使用以下注解:
@JsonDeserialize(using = CustomDeserializer.class)
class GeneralObject {
...
}
要阻止无限递归循环的发生,必须对所有子类进行注释以不使用此自定义反序列化器,并且我们需要引入一个帮助器类来停止 GeneralObject
的递归:
@JsonDeserialize(using = JsonDeserializer.None.class)
class SpecialObject extends GeneralObject {
public String specialProp;
}
@JsonDeserialize(using = JsonDeserializer.None.class)
class RecursionStopper extends GeneralObject {
// this class intentionally empty
}
反序列化按预期工作,也适用于嵌套对象:
ObjectMapper mapper = new ObjectMapper();
String objString = "{\n" +
" \"objType\": \"someObjType\",\n" +
" \"commonProp\": \"example3...\",\n" +
" \"nestedObject\": {\n" +
" \"objType\": \"SPECIAL\",\n" +
" \"commonProp\": \"example2...\",\n" +
" \"specialProp\": \"more example\"\n" +
" }\n" +
"}";
GeneralObject genObj = mapper.readValue(objString,GeneralObject.class);
System.out.println(((SpecialObject) genObj.nestedObject).specialProp);
以上是大佬教程为你收集整理的具有“默认”对象类型的嵌套对象的动态反序列化全部内容,希望文章能够帮你解决具有“默认”对象类型的嵌套对象的动态反序列化所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。