From 8edb4b97292e59b0b96a8deecd3b058e94b744a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Fri, 13 Oct 2023 21:16:43 -0600 Subject: [PATCH] Add properties for configuring EnumFeature and JsonNodeFeature Both `EnumFeature` and `JsonNodeFeature` implement `DataTypeFeature` which was recently added in Spring Framework. This commits introduces support to allow the configuration via properties. See spring-projects/spring-framework#31380 See gh-37885 --- .../jackson/JacksonAutoConfiguration.java | 2 ++ .../jackson/JacksonProperties.java | 23 +++++++++++++++++- .../JacksonAutoConfigurationTests.java | 24 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java index a6aa97773ed..68cc6f27e02 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.java @@ -213,6 +213,8 @@ public class JacksonAutoConfiguration { configureFeatures(builder, this.jacksonProperties.getMapper()); configureFeatures(builder, this.jacksonProperties.getParser()); configureFeatures(builder, this.jacksonProperties.getGenerator()); + configureFeatures(builder, this.jacksonProperties.getEnumDatatype()); + configureFeatures(builder, this.jacksonProperties.getJsonNodeDatatype()); configureDateFormat(builder); configurePropertyNamingStrategy(builder); configureModules(builder); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java index 805604e9830..a886d7a9224 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jackson/JacksonProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,8 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.cfg.EnumFeature; +import com.fasterxml.jackson.databind.cfg.JsonNodeFeature; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -38,6 +40,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @author Andy Wilkinson * @author Marcel Overdijk * @author Johannes Edmeier + * @author Eddú Meléndez * @since 1.2.0 */ @ConfigurationProperties(prefix = "spring.jackson") @@ -86,6 +89,16 @@ public class JacksonProperties { */ private final Map generator = new EnumMap<>(JsonGenerator.Feature.class); + /** + * Jackson on/off features for enum types. + */ + private final Map enumDatatype = new EnumMap<>(EnumFeature.class); + + /** + * Jackson on/off features for JsonNode types. + */ + private final Map jsonNodeDatatype = new EnumMap<>(JsonNodeFeature.class); + /** * Controls the inclusion of properties during serialization. Configured with one of * the values in Jackson's JsonInclude.Include enumeration. @@ -154,6 +167,14 @@ public class JacksonProperties { return this.generator; } + public Map getEnumDatatype() { + return this.enumDatatype; + } + + public Map getJsonNodeDatatype() { + return this.jsonNodeDatatype; + } + public JsonInclude.Include getDefaultPropertyInclusion() { return this.defaultPropertyInclusion; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java index 3c14adc3ef3..3528fc8afd6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfigurationTests.java @@ -45,6 +45,8 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.cfg.ConstructorDetector; import com.fasterxml.jackson.databind.cfg.ConstructorDetector.SingleArgConstructor; +import com.fasterxml.jackson.databind.cfg.EnumFeature; +import com.fasterxml.jackson.databind.cfg.JsonNodeFeature; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.util.StdDateFormat; @@ -88,6 +90,7 @@ import static org.mockito.Mockito.mock; * @author Johannes Edmeier * @author Grzegorz Poznachowski * @author Ralf Ueberfuhr + * @author Eddú Meléndez */ class JacksonAutoConfigurationTests { @@ -289,6 +292,27 @@ class JacksonAutoConfigurationTests { }); } + @Test + void enableEnumFeature() { + this.contextRunner.withPropertyValues("spring.jackson.enum-data-type.write_enums_to_lowercase:true") + .run((context) -> { + ObjectMapper mapper = context.getBean(ObjectMapper.class); + assertThat(EnumFeature.WRITE_ENUMS_TO_LOWERCASE.enabledByDefault()).isFalse(); + assertThat(mapper.getSerializationConfig().isEnabled(EnumFeature.WRITE_ENUMS_TO_LOWERCASE)).isTrue(); + }); + } + + @Test + void disableJsonNodeFeature() { + this.contextRunner.withPropertyValues("spring.jackson.json-node-data-type.write_null_properties:false") + .run((context) -> { + ObjectMapper mapper = context.getBean(ObjectMapper.class); + assertThat(JsonNodeFeature.WRITE_NULL_PROPERTIES.enabledByDefault()).isTrue(); + assertThat(mapper.getDeserializationConfig().isEnabled(JsonNodeFeature.WRITE_NULL_PROPERTIES)) + .isFalse(); + }); + } + @Test void moduleBeansAndWellKnownModulesAreRegisteredWithTheObjectMapperBuilder() { this.contextRunner.withUserConfiguration(ModuleConfig.class).run((context) -> {