diff --git a/spring-web/spring-web.gradle b/spring-web/spring-web.gradle index 8f74029c8c..d0823660f6 100644 --- a/spring-web/spring-web.gradle +++ b/spring-web/spring-web.gradle @@ -81,6 +81,7 @@ dependencies { testImplementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8") testImplementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin") + testImplementation("com.fasterxml.jackson.module:jackson-module-parameter-names") testImplementation("com.squareup.okhttp3:mockwebserver") testImplementation("io.micrometer:micrometer-observation-test") testImplementation("io.projectreactor:reactor-test") diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java index 9c11e50b34..b6a236428a 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java @@ -859,6 +859,16 @@ public class Jackson2ObjectMapperBuilder { // jackson-datatype-jdk8 not available } + try { + Class parameterNamesModuleClass = (Class) + ClassUtils.forName("com.fasterxml.jackson.module.paramnames.ParameterNamesModule", this.moduleClassLoader); + Module parameterNamesModule = BeanUtils.instantiateClass(parameterNamesModuleClass); + modulesToRegister.set(parameterNamesModule.getTypeId(), parameterNamesModule); + } + catch (ClassNotFoundException ex) { + // jackson-module-parameter-names not available + } + try { Class javaTimeModuleClass = (Class) ClassUtils.forName("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", this.moduleClassLoader); diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java index a9beb0d284..7198d78895 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java @@ -85,6 +85,8 @@ import org.springframework.http.ProblemDetail; import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** @@ -255,6 +257,25 @@ class Jackson2ObjectMapperBuilderTests { assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null).getClass()).isSameAs(CustomIntegerSerializer.class); } + static class ParameterModuleDto { + + int x; + int y; + + ParameterModuleDto(int x, int y) { + this.x = x; + this.y = y; + } + + int getX() { + return x; + } + + int getY() { + return y; + } + } + @Test void wellKnownModules() throws JsonProcessingException, UnsupportedEncodingException { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build(); @@ -265,6 +286,9 @@ class Jackson2ObjectMapperBuilderTests { Optional optional = Optional.of("test"); assertThat(new String(objectMapper.writeValueAsBytes(optional), "UTF-8")).isEqualTo("\"test\""); + + assertThatCode(() -> objectMapper.readValue("{\"x\":1,\"y\":2}", ParameterModuleDto.class)).doesNotThrowAnyException(); + // Kotlin module IntRange range = new IntRange(1, 3); assertThat(new String(objectMapper.writeValueAsBytes(range), "UTF-8")).isEqualTo("{\"start\":1,\"end\":3}");