Skip to content

Nested type arguments doesn't work with polymorphic types #1604

@Raniz85

Description

@Raniz85

When using @JsonSubTypes/@JsonTypeInfo on an interface with a generic parameter (de)serialising a subclass that wraps it's own generic parameter in another generic class or interface doesn't work.

It's a bit complex to explain with words so here's a short example:

public class GenericPolymorphismTest {
    @JsonTypeInfo(property = "type", use = JsonTypeInfo.Id.NAME)
    @JsonSubTypes({
            @JsonSubTypes.Type(value = AddToList.class, name = "addToList")
    })
    public interface Operation<T> {
        T perform(T operand);
    }

    public static class AddToList<T> implements Operation<List<T>> {
        T value;
        @Override
        public List<T> perform(List<T> operand) {
            operand.add(value);
            return operand;
        }
    }

    public static class Container {
        Operation<List<UUID>> listOperation;
    }

    private static final ObjectMapper objectMapper = new ObjectMapper();
    static {
        objectMapper.setVisibility(new VisibilityChecker.Std(JsonAutoDetect.Visibility.ANY));
    }

    public static void main(String[] args) throws JsonProcessingException {
        AddToList<UUID> addToList = new AddToList<>();
        addToList.value = UUID.randomUUID();
        Container container = new Container();
        container.listOperation = addToList;

        System.out.println(objectMapper.writeValueAsString(container));
    }
}

This crashes with the following exception:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Class java.util.UUID not subtype of [collection type; class java.util.List, contains [simple type, class java.util.UUID]] (through reference chain: GenericPolymorphismTest$Container["listOperation"]->GenericPolymorphismTest$AddToList["value"])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388)
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348)
	at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:343)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:698)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeWithType(BeanSerializerBase.java:581)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:706)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
	at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3681)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3057)
	at GenericPolymorphismTest.main(GenericPolymorphismTest.java:57)
Caused by: java.lang.IllegalArgumentException: Class java.util.UUID not subtype of [collection type; class java.util.List, contains [simple type, class java.util.UUID]]
	at com.fasterxml.jackson.databind.type.TypeFactory.constructSpecializedType(TypeFactory.java:359)
	at com.fasterxml.jackson.databind.cfg.MapperConfig.constructSpecializedType(MapperConfig.java:306)
	at com.fasterxml.jackson.databind.DatabindContext.constructSpecializedType(DatabindContext.java:149)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._findAndAddDynamic(BeanPropertyWriter.java:870)
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:682)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)
	... 8 more

If I try work around it by making value into a List<T> deserialisation works but serialisation gives me a List<String> instead of List<UUID> so using a list after perform will throw ClassCastExceptions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions