Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Enum deserialization to use @JsonProperty, @JsonAlias even if EnumNamingStrategy used #4037

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,29 @@ public static EnumResolver constructUsingEnumNamingStrategy(DeserializationConfi
final Enum<?>[] enumConstants = _enumConstants(enumCls0);
HashMap<String, Enum<?>> 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,
Expand All @@ -339,14 +357,32 @@ public static EnumResolver constructUsingEnumNamingStrategy(DeserializationConfi
final Class<?> enumCls0 = annotatedClass.getRawType();
final Class<Enum<?>> 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<String, Enum<?>> 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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down