В настоящее время я пытаюсь реализовать десериализатор, используя Джексона, способного обрабатывать полиморфизм, то есть, учитывая эти два класса:
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]
Это решение не устраивает меня:
Каждый раз, когда мы хотим создать новый подкласс Animal, мы должны
укажите в этом классе, что имя и вес являются свойствами json
Это сложно, например, в классе Animal свойство weight помечается как обязательное, а в подклассах мы можем определить, что weight не является обязательным свойством.
Знаете ли вы способ "наследовать" от свойств родительского класса, чтобы не указывать каждый раз в подклассах соответствующие свойства json?
С наилучшими пожеланиями,
Матье