As of Jackson 2.12.2, the following accomplishes the goal using the “deduction-based polymorphism” feature. If properties distinct to the Bird
subtype (i.e. wingspan
) are present, the deserialized type will be Bird
; else it will be Animal
:
@JsonTypeInfo(use=Id.DEDUCTION, defaultImpl = Animal.class)
@JsonSubTypes({@Type(Bird.class)})
public class Animal {
public String name;
public int age;
}
Deduction-based polymorphism
The deduction-based polymorphism feature deduces subtypes based on the presence of properties distinct to a particular subtype. If there isn’t a subtype uniquely identifiable by the subtype-specific properties, the type specified by defaultImpl
value will be used.
The deduction-based polymorphism feature was implemented per jackson-databind#43 in Jackson 2.12, and is summarized in the 2.12 release notes:
It basically allows omitting of actual Type Id field or value, as long as the subtype can be deduced (
@JsonTypeInfo(use=DEDUCTION)
) from existence of fields. That is, every subtype has a distinct set of fields they included, and so during deserialization type can be uniquely and reliably detected.
This ability to specify a default type — rather than throw an exception — when there is no uniquely identifiable subtype was added by jackson-databind#3055 in Jackson 2.12.2:
In the absence of a single candidate,
defaultImpl
should be the target type regardless of suitability.
A slightly longer explanation of deduction-based polymorphism is given in the Jackson 2.12 Most Wanted (1/5):
Deduction-Based Polymorphism article written by the Jackson creator.