From 85ca9f46dd9e91604846b249927b271671f624a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Tue, 25 Nov 2025 15:55:18 +0100 Subject: [PATCH] Support reading unresolvable types in AbstractJacksonHttpMessageConverter Closes gh-35889 --- .../AbstractJacksonHttpMessageConverter.java | 6 +---- .../JacksonJsonHttpMessageConverterTests.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/converter/AbstractJacksonHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/AbstractJacksonHttpMessageConverter.java index 938576e37ec..6b611b97d3d 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/AbstractJacksonHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/AbstractJacksonHttpMessageConverter.java @@ -264,11 +264,7 @@ public abstract class AbstractJacksonHttpMessageConverter clazz = type.resolve(); - if (clazz == null) { - return false; - } - return this.mapperRegistrations == null || selectMapper(clazz, mediaType) != null; + return this.mapperRegistrations == null || selectMapper(type.toClass(), mediaType) != null; } @Override diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java index 4fc5c6024f4..66964c9f140 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/JacksonJsonHttpMessageConverterTests.java @@ -48,6 +48,7 @@ import tools.jackson.databind.ser.std.SimpleFilterProvider; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ResolvableType; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.testfixture.http.MockHttpInputMessage; import org.springframework.web.testfixture.http.MockHttpOutputMessage; @@ -67,6 +68,8 @@ class JacksonJsonHttpMessageConverterTests { private JacksonJsonHttpMessageConverter converter = new JacksonJsonHttpMessageConverter(); + private final ResolvableType unresolvableType = ResolvableType.forClass(ResponseEntity.class).getNested(2); + @Test void canRead() { @@ -75,6 +78,7 @@ class JacksonJsonHttpMessageConverterTests { assertThat(this.converter.canRead(MyBean.class, new MediaType("application", "json", StandardCharsets.UTF_8))).isTrue(); assertThat(this.converter.canRead(MyBean.class, new MediaType("application", "json", StandardCharsets.US_ASCII))).isTrue(); assertThat(this.converter.canRead(MyBean.class, new MediaType("application", "json", StandardCharsets.ISO_8859_1))).isTrue(); + assertThat(this.converter.canRead(this.unresolvableType, MediaType.APPLICATION_JSON)).isTrue(); } @Test @@ -173,6 +177,29 @@ class JacksonJsonHttpMessageConverterTests { assertThat(result).containsEntry("bool", Boolean.TRUE); assertThat(result).containsEntry("bytes", "AQI="); } + @Test + @SuppressWarnings("unchecked") + void readUnresolable() throws IOException { + String body = "{" + + "\"bytes\":\"AQI=\"," + + "\"array\":[\"Foo\",\"Bar\"]," + + "\"number\":42," + + "\"string\":\"Foo\"," + + "\"bool\":true," + + "\"fraction\":42.0}"; + MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8)); + inputMessage.getHeaders().setContentType(new MediaType("application", "json")); + HashMap result = (HashMap) this.converter.read(this.unresolvableType, inputMessage, null); + assertThat(result).containsEntry("string", "Foo"); + assertThat(result).containsEntry("number", 42); + assertThat((Double) result.get("fraction")).isCloseTo(42D, within(0D)); + List array = new ArrayList<>(); + array.add("Foo"); + array.add("Bar"); + assertThat(result).containsEntry("array", array); + assertThat(result).containsEntry("bool", Boolean.TRUE); + assertThat(result).containsEntry("bytes", "AQI="); + } @Test void write() throws IOException {