Nested type arguments doesn't work with polymorphic types
See original GitHub issueWhen 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.
Issue Analytics
- State:
- Created 6 years ago
- Comments:25 (12 by maintainers)
Top Results From Across the Web
Nested type arguments doesn't work with polymorphic types
I am able to recreate this bug without using polymorphism. Using the following code, the GoodOuter can be serialized correctly, but BadOuter fails....
Read more >Jackson deserializing nested polymorphic type - Stack Overflow
Show activity on this post. I'm trying to use Jakson to deserialize a nested polymorphic type. Meaning my top level type referes to...
Read more >Chapter 6 Polymorphism and its limitations - OCaml
This chapter covers more advanced questions related to the limitations of polymorphic functions and types. There are some situations in OCaml where the...
Read more >15: 38.5. Query Language (SQL) Functions - PostgreSQL
It is permitted to have polymorphic arguments with a fixed return type, but the converse is not. For example: CREATE FUNCTION is_greater(anyelement, anyelement) ......
Read more >Chapter 22: Class Templates - C++ Annotations Version 12.2.0
In such cases template argument deduction is used for the nested class, but (as it is not used for name qualifiers) is not...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@dnno Could you please file a new issue for this: even if the problem is related to this one (caused by fix), it is easier to track fix that way. You can add a reference to this issue as likely root cause.
I can’t say much except that this could be related to / same as #1964, which will be fixed for
2.9.6
Yes. So, just to clarify what I meant: existing type resolution works fine, as is, when only resolving a single type. What is needed here is sort of re-parent things (grafting?), and it could either be implemented as separate recursive process (instead of resolving it is actually walking existing type hierarchy, really), or trying to retrofit resolution with this.
There are further challenges in that type objects are (mostly, ideally should be fully) immutable, to figure out what and how to copy.