我目前正在尝试使用 Jackson 实现一个反序列化器,能够处理多态性。也就是说,假设有这两个类:
public abstract class Animal {
private String name;
private float weight;
@JsonCreator
protected Animal(@JsonProperty(value="name") String name, @JsonProperty(value="weight",required=true) int weight) {
this.name=name;
this.weight=weight;
}
}
public class Dog extends Animal {
private int barkVolume;
@JsonCreator
public Dog(String name,int weight, @JsonProperty(value="barkVolume",required=true) int barkVolume) {
super(name, weight);
this.barkVolume=barkVolume;
}
}
反序列化器应该能够从json字符串中推断并实例化正确的子类。
我使用一个自定义的反序列化器模块,UniquePropertyPolymorphicDeserializer(来自https://gist.github.com/robinhowlett/ce45e575197060b8392d)。此模块的配置如下:
UniquePropertyPolymorphicDeserializer<Animal> deserializer =
new UniquePropertyPolymorphicDeserializer<Animal>(Animal.class);
deserializer.register("barkVolume", Dog.class);
SimpleModule module = new SimpleModule("UniquePropertyPolymorphicDeserializer");
module.addDeserializer(Animal.class, deserializer);
mapper.registerModule(module);
该模块会要求用户输入每个动物子类的独特属性。因此,当反序列化程序发现一个具有"barkVolume"属性的JSON字符串时,便知道应该实例化一只狗。
然而,我对JSON属性规范存在问题,因为子类无法继承父类中给出的属性。在Dog类中,即使这些属性已在Animal类中指定,我还必须再次指定"name"和"weight"为JSON属性:
public Dog(@JsonProperty(value="name") String name, @JsonProperty(value="weight",required=true) int weight, @JsonProperty(value="barkVolume",required=true) int barkVolume) {
super(name, weight);
this.barkVolume=barkVolume;
}
否则,反序列化程序会生成错误:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type `Animals.Dog`: Argument #0 has no property name, is not Injectable: can not use as Creator [constructor for Animals.Dog, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}]
at [Source: UNKNOWN; line: -1, column: -1]
对我来说,这个解决方案并不令人满意:
每次我们想要创建Animal的一个新子类时,都需要在这个类中指定名称和重量是JSON属性。
这很棘手,因为例如,在Animal类中,重量属性被标记为必需的,而在子类中,我们可以定义重量不是必需属性。
您知道有没有一种方法可以从父类继承属性,以避免在子类中每次都指定相应的JSON属性?
最好的问候,
Mathieu