使用jackson注释反序列化多级多态子类型

时间:2017-01-10 13:49:28

标签: json serialization jackson polymorphism deserialization

我想使用jackson注释反序列化2级多态子类型。 基本上我想使用json注释和jacksons将以下json转换为xml如下

{
  "mainSet": {
    "name": "bla bla",
    "myItems": [
      {
        "MySubItem": {
          "id": 1,
          "name": "Value1",
          "itemAProperty1": "Some stuff",
          "itemAProperty2": "Another property value",
          "type": "MySubItemA"
        }
      },
      {
        "MySubItem": {
          "id": 2,
          "name": "Value2",
          "itemBProperty1": 1000,
          "itemBProperty2": "B property",
          "type": "MySubItemB"
        }
      }
    ]
  }
}

我想要的最终Xml是

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<mainTag schemaVersion="1" xmlns="http://www.utiba.com/xml/ns/brms/v1"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <name>bla bla</name>
    <MySubItem xsi:type="MySubItemA" id="1" name="value1" itemAProperty1="Some stuff" itemAProperty2="Another property value"/>
    <MySubItem xsi:type="MySubItemB" id="2" name="value2" itemAProperty1=1000 itemAProperty2="B Property"/>
</mainTag>

我有以下几组课程 - 主要课程

public abstract class MyItem {

private int id;
private String name;
 //getter and setter
}

它有抽象的子类

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MySubItem")
@XmlSeeAlso({
    MySubItemA.class,
    MySubItemB.class,
    MySubItemC.class
})
    public abstract class MySubItem extends MyItem {

    private String itemAProperty1;
    private String itemAProperty2;
     //getter and setter
    }

MySubItem有具体的子条款说 MySubItemA,MySubItemB,MySubItemC

现在最后,我们创建一个包含抽象类

对象列表的客户端类
 import java.util.ArrayList;
    import java.util.List;

    public class MainSet{
     @XmlElements({
        @XmlElement(name = "MysubItem", type = MySubItem.class),
    })
    private List<MyItem> myItems;

      public List<MyItem> getMyItems() {
        return this.myItems;
    }
    }

我尝试为MyItem创建Mixin类

@JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.PROPERTY, property="itemType")
@JsonSubTypes({
   @Type(MySubItem.class)
})

for和MySubItem

@JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.PROPERTY, property="type")
@JsonSubTypes({
   @Type(MySubItemA.class)
   @Type(MySubItemB.class)
   @Type(MySubItemC.class)
})

我得到的错误是:

Error parsing JSON from client: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of MySubItem, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: java.io.StringReader@26bd8952; line: 1, column: 498] (through reference chain: bla bla class ["mainSet"]->com.bla.bla["myItems"])

ISSUE:为myItems列表创建mixin类,具有2级抽象子类层次结构

2 个答案:

答案 0 :(得分:0)

您的子类型注释告诉JAXB该做什么但不告诉Jackson,这是尝试从JSON反序列化您的请求的原因。除了TypeInfo

之外,请尝试将其添加到抽象类中
@JsonSubTypes({
    MySubItemA.class,
    MySubItemB.class,
    MySubItemC.class
})

答案 1 :(得分:0)

Jackson api不支持多级多态类型层次结构。

您可以查看:https://github.com/FasterXML/jackson-databind/issues/374

所以你需要做的是:

请创建一个反序列化器(对于MySubItem.class说MySubItemDeserializerMixin.class)并将其配置为jsonMapper,就像我们对其他Mixin类一样。

from

MySubItemDeserializerMixin.java看起来像:

mapper.addMixInAnnotations(MySubItem.class, MySubItemDeserializerMixin.class);

您还需要为MySubItemDeserializerMixin.java中指定的MySubItem创建反序列化器(MySubItemDeserializer)。

现在你需要创建如下所示的MySubItemMixin.java:

@JsonDeserialize(using = MySubItemDeserializer.class)
public abstract class MySubItemDeserializerMixin{
}

在MySubItemDeserializer中,您可以执行以下操作:

@JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.PROPERTY, property="type")
@JsonSubTypes({
@Type(MySubItemA.class)
@Type(MySubItemB.class)
@Type(MySubItemC.class)
})

希望能解决您的疑虑。

谢谢&amp;此致

Nakul Vashishth