Skip to content

Deserialization of a certain kinds of parametrized properties fail to resolve ? into expected bounds, resulting in LinkedHashMap #4118

Description

@mariuszpala

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.

image

But when I remove the "<?>" from the "extends", then the IDE complains about it, but the deserialization works just fine

image image

Version Information

2.15.2, JDK17

Reproduction

  1. 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());
  1. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.1has-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions