jackson-databind: Deserialization of a certain kinds of parametrized properties fail to resolve `?` into expected bounds, resulting in `LinkedHashMap`
Search before asking
- I searched in the issues and found nothing similar.
Describe the bug
Recently our code editor advices as to change the class definition, the deserialization stopped working correctly.
We have such a class:
public class TestAttribute<T extends TestAttribute<?>> {
protected List<T> attributes;
}
When we create a parent object with a list of such properties 2-level deep, on 2rd level the deserialization doesn’t work and it deserializes into LinkedHashMap instead of TestAttribute. See the screenshot below.
But when I remove the “<?>” from the “extends”, then the IDE complains about it, but the deserialization works just fine
Version Information
2.15.2, JDK17
Reproduction
- Brief code sample/snippet: include here in preformatted/code section
public class TestAttribute<T extends TestAttribute<?> {
protected List<T> attributes;
public TestAttribute() {
}
public TestAttribute(List<T> attributes) {
this.attributes = attributes;
}
public List<T> getAttributes() {
return attributes;
}
public void setAttributes(List<T> attributes) {
this.attributes = attributes;
}
}
public class TestObject {
private List<TestAttribute<?>> attributes = new ArrayList<>();
public TestObject() {
}
public TestObject(List<TestAttribute<?>> attributes) {
this.attributes = attributes;
}
public List<TestAttribute<?>> getAttributes() {
return attributes;
}
public void setAttributes(List<TestAttribute<?>> attributes) {
this.attributes = attributes;
}
}
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
TestAttribute a = new TestAttribute(null);
TestAttribute b = new TestAttribute(List.of(a));
TestAttribute c = new TestAttribute(List.of(b));
TestObject test = new TestObject(List.of(c));
String serialized = objectMapper.writeValueAsString(test);
System.out.println(serialized);
TestObject deserialized = objectMapper.readValue(serialized, TestObject.class);
System.out.println(deserialized.getAttributes().get(0).getAttributes().get(0).getClass().getName());
- Textual explanation: include here When the code above is executed, the last line fails
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.me.samples.TestAttribute (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.me.samples.TestAttribute is in unnamed module of loader 'app')
at com.me.samples.PlainTest.main(PlainTest.java:38)
Expected behavior
Deserialization should work just fine and deserialize a list of TestAttribute objects correctly but instead the LinkedHashMap is deserialized instead unless I remove <?> from all my code which keeps the IDE complaining abut the missing raw parameter.
Additional context
No response
About this issue
- Original URL
- State: open
- Created 9 months ago
- Comments: 22 (20 by maintainers)
Commits related to this issue
- Add reproduction (unit test) for #4118 (#4128) * add test * clean up — committed to FasterXML/jackson-databind by JooHyukKim 9 months ago
- Revert (parts of) #4122, undoes fix to #4118 — committed to FasterXML/jackson-databind by cowtowncoder 9 months ago
- Move #4118 under failing — committed to FasterXML/jackson-databind by cowtowncoder 9 months ago
@poolsnowhui that looks like a Spring WebMVC problem, not Jackson’s.