我们遇到的基本问题是当存在一个类型为基类的属性时,如何处理JSON的反序列化,该基类可以是多个子类中的任何一个。关于这个主题有很多问题,绝大多数似乎都指出在基类上使用JSONSubTypes注释。
一般的例子如下,其中动物可以是几种类型 - 狗,猫,马等......
public class Pets {
private List<Animal> myPets;
public List<Animal> getMyPets(){
return myPets;
}
}
在评论中埋葬通常是一个评论,反对每次添加子类时更改基类的要求。请考虑以下示例。如果创建了一个“Horse”类并且需要使用它,则需要将新类型添加到Horse类的JsonSubTypes列表中。
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "Dog"),
@JsonSubTypes.Type(value = Cat.class, name = "Cat") }
)
public abstract class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
如果基类和所有子类不在同一个jar文件中,那么这里的问题是什么?您现在最终得到循环依赖。子类依赖于具有基类的jar文件,并且基类依赖于具有子类的jar。
JAXB有一种方法可以通过在属性本身上添加子类列表来处理这个问题。如下所示:
@XmlElements({@XmlElement(name="dog" type=Dog.class),
@XmlElement(name="cat" type=Cat.class)})
public List<Animals> getMyPets(){
return myPets;
}
无论如何,杰克逊还是不需要将子类型添加到基类的替代解决方案吗?
答案 0 :(得分:2)
如果您乐意将类名(部分)放在JSON中而不是您指定的自定义名称,则可以跳过@JsonSubTypes
并按名称列出子类型。例如。
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY)
abstract class Animal {
会导致Pets
的序列化(注意类名前的点):
{ “myPets”:[{ “@ C”: “犬”, “姓名”: “N”},{ “@ C”: “名称”, “目录”: “N”}]}
或use = JsonTypeInfo.Id.CLASS
您也可以获得完整的套餐:
的文档{ “myPets”:[
{ “@class”: “com.example.Dog”, “名”: “N”},
{ “@class”: “com.example.Cat”, “名”: “N”}
]}
或者,如果Animal
的所有子类都在同一个包中(不同于Animal
)并且您在其中定义ObjectMapper
,则可以使用mixins指定子类型并避免“循环”依赖“:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "Dog"),
@JsonSubTypes.Type(value = Cat.class, name = "Cat") }
)
interface AnimalMixIn {}
和
mapper.addMixIn(Animal.class, AnimalMixIn.class);
在这种情况下,@JsonTypeInfo
上没有@JsonSubTypes
,Animal