diff --git a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java index c546b18fff..4023be055c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java @@ -313,11 +313,29 @@ public static EnumResolver constructUsingEnumNamingStrategy(DeserializationConfi final Enum[] enumConstants = _enumConstants(enumCls0); HashMap> map = new HashMap<>(); + // introspect + final String[] names = new String[enumConstants.length]; + final String[][] allAliases = new String[enumConstants.length][]; + if (ai != null) { + ai.findEnumValues(enumCls, enumConstants, names); + ai.findEnumAliases(enumCls, enumConstants, allAliases); + } + // from last to first, so that in case of duplicate values, first wins for (int i = enumConstants.length; --i >= 0; ) { Enum anEnum = enumConstants[i]; - String translatedExternalValue = enumNamingStrategy.convertEnumToExternalName(anEnum.name()); - map.put(translatedExternalValue, anEnum); + String name = names[i]; + if (name == null) { + name = enumNamingStrategy.convertEnumToExternalName(anEnum.name()); + } + map.put(name, anEnum); + String[] aliases = allAliases[i]; + if (aliases != null) { + for (String alias : aliases) { + // avoid replacing any primary names + map.putIfAbsent(alias, anEnum); + } + } } return new EnumResolver(enumCls, enumConstants, map, @@ -339,14 +357,32 @@ public static EnumResolver constructUsingEnumNamingStrategy(DeserializationConfi final Class enumCls0 = annotatedClass.getRawType(); final Class> enumCls = _enumClass(enumCls0); final Enum[] enumConstants = _enumConstants(enumCls0); + + // introspect + final String[] names = new String[enumConstants.length]; + final String[][] allAliases = new String[enumConstants.length][]; + if (ai != null) { + ai.findEnumValues(config, annotatedClass, enumConstants, names); + ai.findEnumAliases(config, annotatedClass, enumConstants, allAliases); + } // finally build // from last to first, so that in case of duplicate values, first wins HashMap> map = new HashMap<>(); for (int i = enumConstants.length; --i >= 0; ) { Enum anEnum = enumConstants[i]; - String translatedExternalValue = enumNamingStrategy.convertEnumToExternalName(anEnum.name()); - map.put(translatedExternalValue, anEnum); + String name = names[i]; + if (name == null) { + name = enumNamingStrategy.convertEnumToExternalName(anEnum.name()); + } + map.put(name, anEnum); + String[] aliases = allAliases[i]; + if (aliases != null) { + for (String alias : aliases) { + // avoid replacing any primary names + map.putIfAbsent(alias, anEnum); + } + } } return new EnumResolver(enumCls, enumConstants, map, diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumNamingDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumNamingDeserializationTest.java index c7ebc9d3c6..86256c158e 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumNamingDeserializationTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumNamingDeserializationTest.java @@ -1,5 +1,6 @@ package com.fasterxml.jackson.databind.deser.enums; +import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; import com.fasterxml.jackson.annotation.JsonProperty; @@ -49,6 +50,15 @@ static enum EnumFlavorE { PEANUT_BUTTER } + @EnumNaming(EnumNamingStrategies.CamelCaseStrategy.class) + static enum EnumFlavorF { + PEANUT_BUTTER, + @JsonProperty("caramel") + SALTED_CARAMEL, + @JsonAlias({"darkChocolate", "milkChocolate", "whiteChocolate"}) + CHOCOLATE; + } + static class EnumSauceWrapperBean { public EnumSauceC sauce; @@ -123,6 +133,25 @@ public void testOriginalEnamValueShouldNotBeFoundWithEnumNamingStrategy() throws assertNull(result); } + public void testEnumNamingWithAliasOrProperty() throws Exception { + EnumFlavorF pb = MAPPER.readValue(q("peanutButter"), EnumFlavorF.class); + assertEquals(EnumFlavorF.PEANUT_BUTTER, pb); + + EnumFlavorF chocolate = MAPPER.readValue(q("chocolate"), EnumFlavorF.class); + assertEquals(EnumFlavorF.CHOCOLATE, chocolate); + + EnumFlavorF milk = MAPPER.readValue(q("milkChocolate"), EnumFlavorF.class); + assertEquals(EnumFlavorF.CHOCOLATE, milk); + + EnumFlavorF caramel = MAPPER.readValue(q("caramel"), EnumFlavorF.class); + assertEquals(EnumFlavorF.SALTED_CARAMEL, caramel); + + EnumFlavorF badCaramel = MAPPER.readerFor(EnumFlavorF.class) + .with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) + .readValue(q("saltedCaramel")); + assertNull(badCaramel); + } + public void testEnumNamingStrategySymmetryReadThenWrite() throws Exception { EnumSauceC result = MAPPER.readValue(q("ketchUp"), EnumSauceC.class); assertEquals(EnumSauceC.KETCH_UP, result);