Using a spin on the zoo example:
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;
}
I want to use polymorphic deserialization to construct Animal
instances if no wingspan is specified, and Bird
instances if it is. In Jackson, untyped deserialization typically looks something like this:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "wingspan",
visible = true,
defaultImpl = Animal.class
)
@JsonSubTypes({
@Type(value = Bird.class, name = "bird")
})
public class Animal {
...
}
The wingspan value can be anything, and without that matching something specifically, Jackson falls back on the defaultImpl class.
I could probably use @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
}
}
However, then I have to manually handle extra values and throw consistent exceptions, and it's not clear if the Animal
would be serialized properly later.
It seems I can use my own TypeResolver
or TypeIdResolver
, but that seems like more work than just deserializing the raw json myself. Additionally, TypeResolver
and TypeIdResolver
seem to intrinsically assume that type info is serialized, so those aren't good to use.
Would it be feasible to implement my own JsonDeserializer
that hooks into the lifecycle to specify type, but still uses basic Jackson annotation processing functionality? I've been having a look at JsonDeserializer.deserializeWithType(...)
, but that seems to delegate deserialization entirely to a TypeDeserializer
. There's also the issue that I'd need to deserialize some of the object before I know which type to use.
Alternatively, there might be a way to target the type of zoo pen, even though it's in the parent object.
Is there a way to do what I want with polymorphic type handling?
Bird
-like subclasses, each with a certain field whose presence identifies that subclass. – Cavil