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

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

Допустим, JSON описывает плоский список со смесью водных и наземных животных.

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

При десериализации я хочу использовать значение 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 ответ


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

@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 и сопоставит его с name поля типа json, а затем вернет соответствующий класс в зависимости от того, какое это имя;

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


Есть идеи?

10000