jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

JsonTypeInfo DEDUCTION causes erroneous WRAPPER_ARRAY with JsonValue

Open chrylis opened this issue 3 years ago • 0 comments

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).

chrylis avatar Aug 22 '22 19:08 chrylis