From 2e301f39b212599972089e5b3125a30873d36e0f 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 support for 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 --- .../jackson/JacksonAutoConfiguration.java | 2 ++ .../jackson/JacksonProperties.java | 23 ++++++++++++++++++- .../JacksonAutoConfigurationTests.java | 21 +++++++++++++++++ 3 files changed, 45 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 a6aa97773ed3..68cc6f27e023 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 void customize(Jackson2ObjectMapperBuilder builder) { 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 805604e98308..a886d7a92241 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.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 @@ * @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 Map getGenerator() { 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 3c14adc3ef3f..f135a6768f08 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.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 @@ * @author Johannes Edmeier * @author Grzegorz Poznachowski * @author Ralf Ueberfuhr + * @author Eddú Meléndez */ class JacksonAutoConfigurationTests { @@ -289,6 +292,24 @@ void defaultObjectMapperBuilder() { }); } + @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) -> {