From c86eb5298ac79a1bca22ced10c0b6a43cc3e1754 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 9 Sep 2025 17:58:16 +0100 Subject: [PATCH] Add configuration property for Jackson's DateTimeFeature See gh-45535 --- .../modules/how-to/pages/spring-mvc.adoc | 4 ++++ .../JacksonAutoConfiguration.java | 1 + .../autoconfigure/JacksonProperties.java | 10 +++++++++ .../JacksonAutoConfigurationTests.java | 22 +++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/spring-mvc.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/spring-mvc.adoc index 937dbfae1bb..054442556c8 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/spring-mvc.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/how-to/pages/spring-mvc.adoc @@ -70,6 +70,10 @@ These features are described in several enums (in Jackson) that map onto propert | `spring.jackson.datatype.json-node.` | `true`, `false` +| javadoc:tools.jackson.databind.DateTimeFeature[] +| `spring.jackson.datetime.` +| `true`, `false` + | javadoc:tools.jackson.databind.DeserializationFeature[] | `spring.jackson.deserialization.` | `true`, `false` diff --git a/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfiguration.java b/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfiguration.java index 4c9301ded70..a6d2907d8c7 100644 --- a/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfiguration.java +++ b/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfiguration.java @@ -175,6 +175,7 @@ public final class JacksonAutoConfiguration { configureFeatures(builder, this.jacksonProperties.getMapper(), builder::configure); configureFeatures(builder, this.jacksonProperties.getRead(), builder::configure); configureFeatures(builder, this.jacksonProperties.getWrite(), builder::configure); + configureFeatures(builder, this.jacksonProperties.getDatetime(), builder::configure); configureFeatures(builder, this.jacksonProperties.getDatatype().getEnum(), builder::configure); configureFeatures(builder, this.jacksonProperties.getDatatype().getJsonNode(), builder::configure); configureDateFormat(builder); diff --git a/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonProperties.java b/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonProperties.java index eab4402de25..b5373825ed7 100644 --- a/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonProperties.java +++ b/module/spring-boot-jackson/src/main/java/org/springframework/boot/jackson/autoconfigure/JacksonProperties.java @@ -30,6 +30,7 @@ import tools.jackson.core.json.JsonWriteFeature; import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.MapperFeature; import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.cfg.DateTimeFeature; import tools.jackson.databind.cfg.EnumFeature; import tools.jackson.databind.cfg.JsonNodeFeature; @@ -90,6 +91,11 @@ public class JacksonProperties { */ private final Map write = new EnumMap<>(JsonWriteFeature.class); + /** + * Jackson on/off features for DateTime processing. + */ + private final Map datetime = new EnumMap<>(DateTimeFeature.class); + /** * Controls the inclusion of properties during serialization. Configured with one of * the values in Jackson's JsonInclude.Include enumeration. @@ -160,6 +166,10 @@ public class JacksonProperties { return this.write; } + public Map getDatetime() { + return this.datetime; + } + public JsonInclude.@Nullable Include getDefaultPropertyInclusion() { return this.defaultPropertyInclusion; } diff --git a/module/spring-boot-jackson/src/test/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfigurationTests.java b/module/spring-boot-jackson/src/test/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfigurationTests.java index 3b3e08d8a5a..95239b79e44 100644 --- a/module/spring-boot-jackson/src/test/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfigurationTests.java +++ b/module/spring-boot-jackson/src/test/java/org/springframework/boot/jackson/autoconfigure/JacksonAutoConfigurationTests.java @@ -41,6 +41,7 @@ import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.ValueSerializer; import tools.jackson.databind.cfg.ConstructorDetector; import tools.jackson.databind.cfg.ConstructorDetector.SingleArgConstructor; +import tools.jackson.databind.cfg.DateTimeFeature; import tools.jackson.databind.cfg.EnumFeature; import tools.jackson.databind.cfg.JsonNodeFeature; import tools.jackson.databind.exc.InvalidFormatException; @@ -262,6 +263,27 @@ class JacksonAutoConfigurationTests { }); } + @Test + void enableDatetimeFeature() { + this.contextRunner.withPropertyValues("spring.jackson.datetime.write-dates-as-timestamps:true") + .run((context) -> { + JsonMapper mapper = context.getBean(JsonMapper.class); + DateTimeFeature feature = DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS; + assertThat(feature.enabledByDefault()).isFalse(); + assertThat(mapper.isEnabled(feature)).isTrue(); + }); + } + + @Test + void disableDatetimeFeature() { + this.contextRunner.withPropertyValues("spring.jackson.datetime.adjust-dates-to-context-time-zone:false") + .run((context) -> { + JsonMapper mapper = context.getBean(JsonMapper.class); + assertThat(DateTimeFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE.enabledByDefault()).isTrue(); + assertThat(mapper.isEnabled(DateTimeFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)).isFalse(); + }); + } + @Test void enableEnumFeature() { this.contextRunner.withPropertyValues("spring.jackson.datatype.enum.write-enums-to-lowercase=true")