Может ли Джексон десериализироваться в конкретный подкласс, используя логическое свойство JSON, которое он не записал? - PullRequest
1 голос
/ 15 января 2020

Я использую Джексона для десериализации файла JSON, полученного из других источников, то есть я имею контроль над десериализацией, но не за сериализацией.

Скажем, JSON описывает плоский список со смесью aquati c и наземных животных.

Одним из свойств животного JSON является логическое значение isAquatic. В Java, AquaticAnimal и LandAnimal - отдельные классы, каждый из которых является подклассом абстрактного класса Animal, который содержит данные о членах, относящиеся к обоим подтипам животных. У животных нет других подклассов, и никогда не будет. У животных Aquati c есть такие свойства, как жабры, которые не имеют смысла для LandAnimal (и, таким образом, LandAnimal никогда не будет иметь такого свойства в JSON, а подкласс обеспечивает соответствующее поведение). Аналогично, то же самое верно и в обратном порядке для наземных животных, которые могут иметь p aws, легкие et c. (Это не идеальный пример, но он служит своей цели)

При десериализации я хочу использовать значение isAquatic, чтобы решить, какой подкласс использовать , когда я делаю следующее:

Animal animal = mapper.readValue( ... , Animal.class);

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

Я не до конца понимаю теги Джексона, но основываясь на других примерах, я ' Я хотел бы иметь возможность сделать что-то вроде этого:

@JsonSubTypes({
    @JsonSubTypes.Type(value = LandAnimal.class, isAquatic = false),

    @JsonSubTypes.Type(value = AquaticAnimal.class, isAquatic = true) }
)
public abstract class Animal {
    ...

Я уверен, что это не то, как эта аннотация предназначена для использования, но, надеюсь, это объясняет, что я пытаюсь сделать.

Может кто-нибудь сказать мне, может ли Джексон сделать это, и если да, то как?

1 Ответ

1 голос
/ 15 января 2020

Это возможно с помощью удобной нотации денди:

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "isAquatic")
@JsonSubTypes({
    @JsonSubTypes.Type(value = LandAnimal.class, name = "false"),
    @JsonSubTypes.Type(value = AquaticAnimal.class, name = "true") 
})
public abstract class Animal {
    private String isAquatic;
    ...

это примет ваше свойство isAquatic и отобразит его в поле типа json name, а затем вернет соответствующий класс в зависимости от того, что это имя;

ПРИМЕЧАНИЕ. Я использовал этот подход только с полями, являющимися строками, поэтому, по этой причине я сделал isAquatic строкой, вы можете попробовать другие подходы, чтобы увидеть, работает с логическими значениями.

...