Affects: 5.2.3.RELEASE


Given an endpoint that returns a polymorphic JSON type, eg.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({Impl1.class, Impl2.class})
public interface Parent {
}

public class Impl1 implements Parent {
}

public class Impl2 implements Parent {
}

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public Parent get() {
    return new Impl1();
}

Jackson will serialize it with the property @type, eg.

{
    "@type": "Impl1"
}

However, when wrapping it with an Optional/Page, the JSON polymorphism no longer works. Eg.

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public Optional<Parent> getOptional() {
    return Optional.of(new Impl1());
}

returns:

{}

According to FasterXML/jackson-databind#1594 this is due to type erasure, however the JSON polymorphism still works when wrapping with built-in Collections (eg. List/Set/Map), eg.

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public Collection<Parent> getCollection() {
    return Collections.singleton(new Impl1());
}

So it seems like Spring has special handling for built-in Collections. Is it possible to apply them to Optional/Page as well?

Currently the workaround is to create custom JsonSerializers for Optional/Page, eg.

@JsonComponent
public class OptionalSerializer extends JsonSerializer<Optional<?>> {
    @Override
    public void serialize(Optional<?> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value.isPresent()) {
            gen.writeObject(value.get());
        }
    }
}

Comment From: encircled

Hi.

I can confirm this issue. It works for collections thanks to Jackson support.

My PR fixes "Optional" only, for the Page it should be placed in a different repo I believe, spring-data-rest maybe?

Comment From: zh32

I can confirm this too. Took me a while to find the cause of my problem.

Comment From: poutsma

I don't see a way for Spring Framework to support Spring Data's Page type, so JsonSerializers will still be required for those, but I can add support for Optional.

Comment From: poutsma

This is now fixed. Our apologies for taking this long to resolve this issue.

Comment From: daniel-shuy

@poutsma Thank you! Should I request support for Page in spring-data-commons instead?