jackson-databind
jackson-databind copied to clipboard
JsonTypeInfo DEDUCTION causes erroneous WRAPPER_ARRAY with JsonValue
I'm working on a JSON:API utility library and experimenting with ways to handle its remarkably flexible polymorphism. In this case, I am trying to model links, where the value can be either an object or a string representing a URI.
My initial attempt (which would not entirely work for other reasons) was as follows:
@JsonTypeInfo(use = DEDUCTION)
@JsonSubTypes({
@Type(JsonApiLink.BareUri.class),
@Type(JsonApiLink.LinkObject.class),
})
public abstract class JsonApiLink {
public abstract URI getHref();
@Data
@EqualsAndHashCode(callSuper = false)
public static class BareUri extends JsonApiLink {
@JsonValue
URI href;
}
@Data
@EqualsAndHashCode(callSuper = false)
public static class LinkObject extends JsonApiLink {
URI href;
String rel;
}
}
Invoking jackson.writeValueAsString(new LinkObject(href: uri)) produces the expected "JSON object in a Java string" with no type information, but when I attempt to call jackson.writeValueAsString(new BareUri(uri)), I get the following output:
["com.example.jsonapi.links.JsonApiLink$BareUri","https://links.test/d3a99621-971b-40b1-b8e4-cbbdd3299602"]
It appears that TypeSerializerRerouter is invoked from ToStringSerializerBase#serializeWithType, swaps the @JsonValue's strategy for the subtype's strategy, and then JsonGenerator forgets the DEDUCTION instruction and imposes a default of WRAPPER_ARRAY (JsonGenerator.java:1934 in 2.13.2).