Использование спина на примере зоопарка:
public class ZooPen {
public String type;
public List<Animal> animals;
}
public class Animal {
public String name;
public int age;
}
public class Bird extends Animal {
public double wingspan;
}
Я хочу использовать полиморфную десериализацию для создания экземпляров Animal, если не указано размах крыльев, и экземпляры Bird, если они есть. В Джексоне нетипизированная десериализация обычно выглядит примерно так:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "wingspan",
visible = true,
defaultImpl = Animal.class
)
@JsonSubTypes({
@Type(value = Bird.class, name = **???**)
})
public class Animal {
...
}
Значение wingspan может быть любым, и без этого что-то конкретное, Джексон возвращается к классу defaultImpl.
Возможно, я использовал @JsonCreator
@JsonCreator
public static Animal create(Map<String,Object> jsonMap)
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
if (jsonMap.get("wingspan") == null) {
// Construct and return animal
} else {
// Construct and return bird
}
}
Однако тогда мне приходится вручную обрабатывать дополнительные значения и вызывать непротиворечивые исключения, и неясно, будет ли сериализоваться позднее.
Есть ли способ сделать то, что я хочу, с обработкой полиморфного типа? Кажется, я могу использовать свой собственный TypeResolver или TypeIdResolver, но это похоже на большую работу, чем просто десериализация самого сырого json. В качестве альтернативы, может быть способ нацеливаться на тип руля-зоопарка, даже если он находится в родительском объекте. Любые идеи?
Edit:
TypeResolver и TypeIdResolver, по-видимому, предполагают, что информация о типе сериализована, поэтому они не подходят для использования. Было бы возможно реализовать мой собственный JsonDeserializer, который перехватывает жизненный цикл, чтобы указать тип, но все же использует основные функции обработки аннотаций jackson? Я смотрю на JsonDeserializer.deserializeWithType(...)
, но, похоже, полностью делегирует десериализацию к TypeDeserializer. Там также проблема, что мне нужно будет десериализовать часть объекта, прежде чем я узнаю, какой тип использовать.