【问题标题】:Jackson determine subclass for list field杰克逊确定列表字段的子类
【发布时间】:2019-12-31 06:30:55
【问题描述】:
@Data
public class Parent {
    private String type;
    private List<ChildBase> children;
}
public abstract class ChildBase {
    public void someMethod(){};
}
@Data
public class ChildA extends ChildBase {
    private String bar;
}
@Data
public class ChildB extends ChildBase {
    private String foo;
}

那么,原来的JSON字符串是:

{
  "type": "childA",
  "children": [
    {
       "bar": "baaaar"
    }
  ]
}

如何反序列化这个JSON字符串,反序列化的对象(Parent的实例),它的children字段的实际类型应该是ChildA,因为指定了type字段;

在问题use-property-of-parent-object-to-determine-subclass-when-deserializing 中,答案一击显示了确定子类的方法,因为它不适用于列表字段。

【问题讨论】:

  • 在您提供的链接中,他使用 @JsonTypeInfo(use=Id.NAME, property="kind") @JsonSubTypes({ @Type(value=ExampleNodeT3.class, name="t3"), @Type(value=ExampleNodeT4.class, name="t4")}) 的注释创建了自定义反序列化,您在代码中已经这样做了吗?

标签: java json jackson


【解决方案1】:

对于abstract 类,一种方法是创建自定义反序列化器来实现您想要的效果,如下所示。

因为我不确定 JSON 数组 children 中的所有键是否都相同,例如如果type 分别为childAchildB,则所有键均为barfoo。因此,我使用字段名称来确定 JSON 对象应该被反序列化到哪个类(ChildAChildB)。

代码 sn-p

class ParentDeserializer extends StdDeserializer<Parent> {
    public ParentDeserializer() {
        this(null);
    }

    public ParentDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Parent deserialize(JsonParser jp, DeserializationContext ctx)
        throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        String type = node.get("type").asText();

        List<ChildBase> children = new ArrayList<>();
        node.get("children").forEach(e -> {
            if (e.has("bar")) {
                children.add(new ChildA(e.get("bar").asText()));
            }

            if (e.has("foo")) {
                children.add(new ChildB(e.get("foo").asText()));
            }
        });

        Parent parent = new Parent();
        parent.setType(type);
        parent.setChildren(children);

        return parent;
    }
}

然后使用@JsonDeserialize(using = ParentDeserializer.class)直接在Parent类上注册反序列化器。

@JsonDeserialize(using = ParentDeserializer.class)
class Parent {
    ...
}

【讨论】:

    猜你喜欢
    • 2018-04-07
    • 2016-07-16
    • 2015-02-23
    • 1970-01-01
    • 2015-06-21
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    相关资源
    最近更新 更多