Can Jackson polymorphic deserialization be used to serialize to a subtype if a specific field is present?

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.

Leave a Comment