Джексон: Наследование и обязательные атрибуты - PullRequest
0 голосов
/ 26 июня 2018

В настоящее время я пытаюсь реализовать десериализатор, используя Джексона, способного обрабатывать полиморфизм, то есть, учитывая эти два класса:

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. Таким образом, когда десериализатор находит строку json со свойством barkVolume, он знает, что экземпляр 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?

С наилучшими пожеланиями,

Матье

1 Ответ

0 голосов
/ 11 июля 2018

Я наконец решил создать свой собственный десериализатор (вместо UniquePropertyDeserializer), в котором я использую самоанализ для получения полей родительского класса. Это позволяет избежать повторного указания в дочерних классах требуемых свойств json.

...