-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Closed
Milestone
Description
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 ClassCastException
s.
Metadata
Metadata
Assignees
Labels
No labels