java - 编写多个自定义 Jackson 反序列化器来处理继承的正确方法

标签 java json serialization jackson json-deserialization

我想用 Jackson 反序列化一组相当复杂的 JSON 文档。为了处理继承,我实现了一些自定义反序列化器。

要选择相关类,我必须检查下一个节点的属性。因此,我阅读了树,检查了属性并选择了正确的类。

之后,我通过 mapper.readerFor(targetClass).readValue(rootNode) 读取 JSON。直到这里一切都很好。

但是当我使用 mapper.readerFor(...) 时,下一个调用的序列化程序会获取 ObjectReader 实例而不是 ObjectMapper。但我需要一个 ObjectMapper 实例。

我怎样才能做得更好?

这是我的反序列化器之一,它导致了我的问题:

public AbstractParametersObject deserialize(JsonParser p, DeserializationContext ctxt) 
    throws IOException, JsonProcessingException {

    Class<? extends AbstractParametersObject> targetClass = null;
    ObjectMapper mapper = (ObjectMapper) p.getCodec();
    ObjectNode root =mapper.readTree(p);
    boolean isReference = root.has("$ref");
    boolean isParameter = root.has("in");

    if (isReference) targetClass = ParameterAsReference.class;
    else if (isParameter) {
        targetClass = Optional.of(root.get("in")).map(JsonNode::asText).map(value -> {
            Class<? extends AbstractParametersObject> effectiveClass = null;

            switch (value) {
                case "body": effectiveClass = BodyParameterObject.class;
                    break;
                case "query": effectiveClass = QueryParameterObject.class;
                    break;
                case "path": effectiveClass = PathParameterObject.class;
                    break;
                case "formData": effectiveClass = FormDataParameterObject.class;
                    break;
                case "header": effectiveClass = HeaderParameterObject.class;
                    break;
            }

            return effectiveClass;
        }).orElseThrow(() -> new IllegalArgumentException("todo"));
    }

    AbstractParametersObject parametersObject = mapper.readerFor(targetClass)
                                                      .readValue(root);
    return parametersObject;
}

最佳答案

这可能比您想象的要容易,尽管在没有看到您的一些 JSON 示例的情况下我无法确定。 Jackson 可以直接处理多态性,无需使用 @JsonTypeInfo 和 @JsonSubTypes 注释的自定义序列化器,只要有一个字段的值指示要创建哪个子类即可。例如,假设我有两个不同的文档,它们共享一些公共(public)字段:

{ "type":"square", "name":"my square", "x":12, "y":34, "size":22 }
{ "type":"rectangle", "name":"my rect", "x":9, "y":11, "width":4, "height":9 }

这可以注释为:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, property="type")
@JsonSubTypes({ 
    @Type(name = "square", value = Square.class),
    @Type(name = "rectangle", value = Rectangle.class)
})
public abstract class Shape {
   public String name;
   public int x;
   public int y;
}
public class Square extends Shape {
   public int size;
}
public class Rectangle extends Shape {
   public int width;
   public int height;
}

关于java - 编写多个自定义 Jackson 反序列化器来处理继承的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42596275/

相关文章:

java - 如何从 java 类中获取 scala 中定义的对象中的特征类?

java - 如何在 android studio 中安排特定日期和时间的通知?

java - 在 Java(或 Scala)中迭代 HashMap 的 HashMap

javascript - jquery图像 slider ?

javascript - 如何在 Vue js 中解析 json 以在模板中使用它

java - 如何将从串口接收到的字节转换为十六进制?

java - 如何使用 DOM append 现有 XML 文件而不覆盖现有数据?

objective-c - SBJSON 编码包含另一个对象数组的对象

java - 使用 Gson 将基类列表反序列化为派生类

c# - 通过 DataContract 序列化为 XML : custom output?