What I Want to Do
I want to use Jackson to deserialize a polymorphic type, using the standard @JsonTypeInfo
annotation as follows:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = As.EXISTING_PROPERTY,
property = "identifier")
@JsonSubTypes({@Type(value = A.class, name = "A"),
@Type(value = B.class, name = "B")})
abstract Class Base {}
Class A implements Base {
public String identifier = "A";
}
Class B implements Base {
public String identifier = "B";
}
Class Decorated {
public String decoration = "DECORATION";
@JsonUnwrapped
public Base base;
}
/*
Serialized instance of Decorated WITHOUT @JsonUnwrapped:
{
"decoration" : "DECORATION",
"base" : {
"identifier" : "A"
}
}
Serialized instance of Decorated WITH @JsonUnwrapped:
{
"decoration" : "DECORATION",
"identifier" : "A"
}
*/
Related post: Deserialize JSON with Jackson into Polymorphic Types - A Complete Example is giving me a compile error
This can normally be deserialized by Jackson as follows:
public Object deserialize(String body, Class clazz) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(body, clazz);
}
(And this would work if the @JsonUnwrapped annotation were removed)
The Problem
Polymorphic types do not play well with Jackson's @JsonUnwrapped
annotation, as discussed in this Jira ticket from 2012:
http://markmail.org/message/pogcetxja6goycws#query:+page:1+mid:pogcetxja6goycws+state:results
Handle polymorphic types with @JsonUnwrapped
Agreed - while fixing things is obviously preferable, improving error messages would be useful if that can't be done.
Unwrapping is one of features where implementations gets complicated enough that any bugs cropping up (on deserialization esp) tend to be antibiotic-resistant...
Hardly encouraging.
Three years later:
http://markmail.org/message/cyeyc2ousjp72lh3
Handle polymorphic types with @JsonUnwrapped
Resolution: Won't Fix
Damn.
So, is there any way to coax Jackson into giving me this behaviour without modifying deserialize()
or removing the @JsonUnwrapped
annotation?
My SinglePolyUnwrappedDeserializer
from this Gist can handle a single polymorphic @JsonUnwrapped
property. It's in Kotlin, but can easily be ported to Java if needed. Example:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes(
JsonSubTypes.Type(value = A::class, name = "a"),
JsonSubTypes.Type(value = B::class, name = "b")
)
abstract class Base
data class A(val x: Int) : Base()
data class B(val y: Boolean) : Base()
@JsonDeserialize(using = SinglePolyUnwrappedDeserializer::class)
data class C(val a: String, @JsonUnwrapped val b: Base)
AFAIK, all combinations of other annotations are supported. The only limitation is that there is exactly one @JsonUnwrapped
property.
If you also need a generic serializer for polymorphic @JsonUnwrapped
, you can write it yourself very easily without any reflection or introspection: just merge the ObjectNode
of the inner object onto the ObjectNode
of the containing object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With