Skip to content

Commit 1cd14c9

Browse files
committed
Configure ProblemDetailJacksonMixin on JsonMapper
Prior to this commit, Spring Boot would use Framework's `Jackson2ObjectMapperBuilder` to configure the `ObjectMapper` instance. This builder would configure the `ProblemDetail` mixin automatically. With the introduction of Jackson 3.x support, Spring Framework removed its builder in favor of the native Jackson builder. As a result, the mixin is not registered with the `JsonMapper` aymore. This commit ensures that the mixin is registered if the `ProblemDetail` class is present in the classpath. Closes gh-47298
1 parent 51b606e commit 1cd14c9

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

module/spring-boot-jackson/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ dependencies {
2828
api(project(":core:spring-boot"))
2929
api("tools.jackson.core:jackson-databind")
3030

31-
implementation("org.springframework:spring-web")
32-
3331
optional(project(":core:spring-boot-autoconfigure"))
32+
optional("org.springframework:spring-web")
3433
optional("tools.jackson.dataformat:jackson-dataformat-cbor")
3534
optional("tools.jackson.dataformat:jackson-dataformat-xml")
3635
optional("tools.jackson.module:jackson-module-jakarta-xmlbind-annotations")

module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfiguration.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
import org.springframework.context.annotation.Primary;
6060
import org.springframework.context.annotation.Scope;
6161
import org.springframework.core.Ordered;
62+
import org.springframework.http.ProblemDetail;
63+
import org.springframework.http.converter.json.ProblemDetailJacksonMixin;
6264
import org.springframework.util.Assert;
6365
import org.springframework.util.ClassUtils;
6466
import org.springframework.util.ReflectionUtils;
@@ -305,6 +307,26 @@ private void configureConstructorDetector(JsonMapper.Builder builder) {
305307

306308
}
307309

310+
@Configuration(proxyBeanMethods = false)
311+
@ConditionalOnClass(ProblemDetail.class)
312+
static class ProblemDetailsConfiguration {
313+
314+
@Bean
315+
ProblemDetailJsonMapperBuilderCustomizer problemDetailJsonMapperBuilderCustomizer() {
316+
return new ProblemDetailJsonMapperBuilderCustomizer();
317+
}
318+
319+
static final class ProblemDetailJsonMapperBuilderCustomizer implements JsonMapperBuilderCustomizer {
320+
321+
@Override
322+
public void customize(JsonMapper.Builder builder) {
323+
builder.addMixIn(ProblemDetail.class, ProblemDetailJacksonMixin.class);
324+
}
325+
326+
}
327+
328+
}
329+
308330
static class JacksonAutoConfigurationRuntimeHints implements RuntimeHintsRegistrar {
309331

310332
@Override

module/spring-boot-jackson/src/test/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfigurationTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.springframework.context.annotation.Import;
6868
import org.springframework.context.annotation.Primary;
6969
import org.springframework.core.annotation.Order;
70+
import org.springframework.http.ProblemDetail;
7071

7172
import static org.assertj.core.api.Assertions.assertThat;
7273
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -484,6 +485,17 @@ void shouldRegisterPropertyNamingStrategyHints() {
484485
assertThat(RuntimeHintsPredicates.reflection().onType(PropertyNamingStrategies.class)).accepts(hints);
485486
}
486487

488+
@Test
489+
void shouldRegisterProblemDetailsMixin() {
490+
this.contextRunner.run((context) -> {
491+
ObjectMapper mapper = context.getBean(ObjectMapper.class);
492+
ProblemDetail problemDetail = ProblemDetail.forStatus(404);
493+
problemDetail.setProperty("spring", "boot");
494+
String json = mapper.writeValueAsString(problemDetail);
495+
assertThat(json).isEqualTo("{\"status\":404,\"title\":\"Not Found\",\"spring\":\"boot\"}");
496+
});
497+
}
498+
487499
static class MyDateFormat extends SimpleDateFormat {
488500

489501
MyDateFormat() {

0 commit comments

Comments
 (0)