杰克逊:继承和必需属性

3

我目前正在尝试使用 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]

对我来说,这个解决方案并不令人满意:

  1. 每次我们想要创建Animal的一个新子类时,都需要在这个类中指定名称和重量是JSON属性。

  2. 这很棘手,因为例如,在Animal类中,重量属性被标记为必需的,而在子类中,我们可以定义重量不是必需属性。

您知道有没有一种方法可以从父类继承属性,以避免在子类中每次都指定相应的JSON属性?

最好的问候,

Mathieu

1个回答

0

我最终决定创建自己的反序列化器(而不是使用UniquePropertyDeserializer),其中我使用内省来获取父类的字段。这使得在子类中避免再次指定所需的JSON属性成为可能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接