Полиморфизм Джексона: как сопоставить несколько подтипов в одном классе

Я использую Jackson 1.9.x. Придерживаясь примерами "Животные", вот что я хотел бы сделать:

Скажем, у меня есть класс Animal:

public class Animal {
    private String type;
    // accessors
}

public class Mammal extends Animal {
    private String diet;
    // accessors
}

public class Bird extends Animal {
    private boolean tropical;
    // accessors
}

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

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = Mammal.class, name = "Dog"),
                @JsonSubTypes.Type(value = Mammal.class, name = "Cat"),
                @JsonSubTypes.Type(value = Bird.class, name = "Dodo"},
                @JsonSubTypes.Type(value = Bird.class, name = "Cockatoo"})
public class Animal {

}

То, что я сейчас вижу, - это то, что Джексон узнает только отношение "Собака к Млекопитающему" и "Додо-птица". Это связано с тем, что StdSubtypeResolver._collectAndResolve() позволяет одному и тому же классу регистрироваться один раз (из-за реализации NamedType.equals()).

Есть ли обходной путь к проблеме, которую я вижу?

Ответ 1

Возможно, не используя аннотации. Проблемы возникают из-за того, что такое сопоставление не будет работать для сериализации, и существующее сопоставление ожидает взаимно однозначное (взаимное) отношение. Но вы можете захотеть подать RFE в джексон-databind вопрос трекер; добавление поддержки может быть возможно.

Ответ 2

Ошибка была исправлена ​​в версии 2.6.0, поэтому вам просто нужно обновить Jackson до версии 2.6.0 или новее. Дополнительная информация здесь и здесь.

Ответ 3

Я также столкнулся с той же проблемой и выяснил, что отображение подтипов ожидает уникальных классов.

Я сделал, чтобы создать два класса, которые расширяют один и тот же базовый класс. Расширенные классы пусты, поскольку они имеют те же свойства, что и базовый класс. Затем добавили их на карту подтипа. Например, в вашем случае это будет -

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({@JsonSubTypes.Type(value = Mammal.class, name = "Dog"),
            @JsonSubTypes.Type(value = Mammal.class, name = "Cat"),
            @JsonSubTypes.Type(value = BirdDodo.class, name = "Dodo"},
            @JsonSubTypes.Type(value = BirdCockatoo.class, name = "Cockatoo"})
public class Animal {

}

public class BirdCockatoo extends Cockatoo{}
public class BirdDodo extends Dodo{}

Я понимаю, что это не лучший подход, но пока проблема не будет решена, это может быть лучший способ исправить это. Я уже придерживался этого подхода.

Надеюсь, это поможет вам!