From e088857be632fc220c41436e22cc901f58ea0b67 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Sun, 21 Apr 2024 04:18:55 +0900 Subject: [PATCH] Allow override `DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE` with `JsonFormat.Feature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE` (#4490) --- release-notes/VERSION-2.x | 4 ++ .../databind/deser/std/EnumDeserializer.java | 14 +++-- .../databind/deser/enums/EnumAltIdTest.java | 54 +++++++++++++++++-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 5084cb7bbb..e328104dd1 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -28,6 +28,10 @@ Project: jackson-databind #4481: Unable to override `DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL` with `JsonFormat.Feature.READ_UNKNOWN_ENUM_VALUES_AS_NULL` (reported by @luozhenyu) +#4489: Unable to override `DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE` + with `JsonFormat.Feature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE` + (reported by Joo-Hyuk K) + (fix by Joo-Hyuk K) 2.17.0 (12-Mar-2024) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java index 7174ae6e59..f3cab75adb 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java @@ -494,8 +494,16 @@ protected boolean useNullForUnknownEnum(DeserializationContext ctxt) { // @since 2.15 protected boolean useDefaultValueForUnknownEnum(DeserializationContext ctxt) { - return (_enumDefaultValue != null) - && (Boolean.TRUE.equals(_useDefaultValueForUnknownEnum) - || ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)); + // If we have a default value... + if (_enumDefaultValue != null) { + // Check if FormatFeature overrides exist first + if (_useDefaultValueForUnknownEnum != null) { + return _useDefaultValueForUnknownEnum; + } + // Otherwise, check the global setting + return ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); + } + // No default value? then false + return false; } } diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumAltIdTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumAltIdTest.java index a8cf41a006..8e2d973c4c 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumAltIdTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumAltIdTest.java @@ -10,10 +10,8 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import static org.junit.jupiter.api.Assertions.*; @@ -103,6 +101,22 @@ static class Book4481 { public Color color; } + enum Types { + @JsonEnumDefaultValue + DEFAULT_TYPE, + FAST, SLOW + } + + static class SpeedWithoutDefaultOverride { + @JsonFormat(without = JsonFormat.Feature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) + public Types type; + } + + static class SpeedWithDefaultOverride { + @JsonFormat(with = JsonFormat.Feature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) + public Types type; + } + /* /********************************************************** /* Test methods, basic @@ -315,6 +329,38 @@ public void testEnumWithNullForUnknownValueEnumSet() throws Exception { assertTrue(pojo.value.contains(MyEnum2352_3.B)); } + /** + * Test to verify that configuration via + * {@link com.fasterxml.jackson.annotation.JsonFormat.Feature#READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE} + * takes precedence over global configuration. + */ + @Test + public void testJsonEnumDefaultValueOverrideOverGlobalConfig() throws Exception { + final String UNKNOWN_JSON = a2q("{'type':'OOPS!'}"); + + // First, global configuration is ENABLED and JsonFeature configuration is DISABLED + // So the test should fail + try { + JsonMapper.builder() + .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) + .build() + .readValue(UNKNOWN_JSON, SpeedWithoutDefaultOverride.class); + fail(); + } catch (InvalidFormatException e) { + verifyException(e, "Cannot deserialize value of type"); + verifyException(e, "not one of the values accepted for Enum class"); + } + + // Second, global configuration is DISABLED and JsonFeature configuration is ENABLED + // So the test should pass + SpeedWithDefaultOverride pojo = JsonMapper.builder() + .disable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE) + .build() + .readValue(UNKNOWN_JSON, SpeedWithDefaultOverride.class); + + assertEquals(Types.DEFAULT_TYPE, pojo.type); + } + /* /********************************************************** /* Test methods, other