Jackson:继承和必需的属性

时间:2018-06-26 12:34:46

标签: java json jackson polymorphism jackson2

我目前正在尝试使用能够处理多态性的杰克逊实现反序列化器,也就是说,给定这两个类:

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);

此模块向用户询问Animal的每个子类的唯一属性。因此,当解串器找到具有barkVolume属性的json字符串时,它知道应该实例化Dog。

但是,我对json属性的规范存在疑问,因为子类不能从父类给出的属性中继承。在Dog类中,我必须再次指定“ name”和“ weight”是json属性,即使在Animal类中已经指定了这些属性:

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类中,将weight属性标记为必需,而在子类中,我们可以定义weight不是必需属性。

您是否知道一种从父类的属性“继承”的方法,从而避免在子类中每次都指定对应的json属性?

最好的问候,

Mathieu

1 个答案:

答案 0 :(得分:0)

我最终决定创建自己的Deserializer(而不是UniquePropertyDeserializer),在其中使用自省功能获取父类的字段。这样可以避免在子类中再次指定所需的json属性。