程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了具有“默认”对象类型的嵌套对象的动态反序列化大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决具有“默认”对象类型的嵌套对象的动态反序列化?

开发过程中遇到具有“默认”对象类型的嵌套对象的动态反序列化的问题如何解决?下面主要结合日常开发的经验,给出你关于具有“默认”对象类型的嵌套对象的动态反序列化的解决方法建议,希望对你解决具有“默认”对象类型的嵌套对象的动态反序列化有所启发或帮助;

我想使用 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,请注明来意。