Полиморфизм Джексона: как сопоставить несколько подтипов в одном классе
Я использую 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{}
Я понимаю, что это не лучший подход, но пока проблема не будет решена, это может быть лучший способ исправить это. Я уже придерживался этого подхода.
Надеюсь, это поможет вам!