EnumNamingDeserializationTest.java
package com.fasterxml.jackson.databind.deser.enums;
import java.util.Map;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.EnumNaming;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static com.fasterxml.jackson.databind.testutil.DatabindTestUtil.*;
public class EnumNamingDeserializationTest
{
private final ObjectMapper MAPPER = newJsonMapper();
private final ObjectMapper MAPPER_CI = jsonMapperBuilder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
.build();
@EnumNaming(EnumNamingStrategies.LowerCamelCaseStrategy.class)
static enum EnumFlavorA {
PEANUT_BUTTER,
SALTED_CARAMEL,
@JsonEnumDefaultValue
VANILLA;
}
@EnumNaming(EnumNamingStrategies.LowerCamelCaseStrategy.class)
static enum EnumFlavorB {
PEANUT_BUTTER,
}
@EnumNaming(EnumNamingStrategies.LowerCamelCaseStrategy.class)
static enum EnumSauceC {
KETCH_UP,
MAYO_NEZZ;
}
@EnumNaming(EnumNamingStrategy.class)
static enum EnumSauceD {
BARBEQ_UE,
SRIRACHA_MAYO;
}
@EnumNaming(EnumNamingStrategies.LowerCamelCaseStrategy.class)
static enum EnumFlavorE {
_PEANUT_BUTTER,
PEANUT__BUTTER,
PEANUT_BUTTER
}
@EnumNaming(EnumNamingStrategies.LowerCamelCaseStrategy.class)
static enum EnumFlavorF {
PEANUT_BUTTER,
@JsonProperty("caramel")
SALTED_CARAMEL,
@JsonAlias({"darkChocolate", "milkChocolate", "whiteChocolate"})
CHOCOLATE;
}
static class EnumSauceWrapperBean {
public EnumSauceC sauce;
@JsonCreator
public EnumSauceWrapperBean(@JsonProperty("sce") EnumSauceC sce) {
this.sauce = sce;
}
}
static class ClassWithEnumMapSauceKey {
@JsonProperty
Map<EnumSauceC, String> map;
}
static class ClassWithEnumMapSauceValue {
@JsonProperty
Map<String, EnumSauceC> map;
}
static enum BaseEnum {
REAL_NAME
}
@EnumNaming(EnumNamingStrategies.LowerCamelCaseStrategy.class)
static enum MixInEnum {
REAL_NAME
}
/*
/**********************************************************
/* Test methods
/**********************************************************
*/
@Test
public void testEnumNamingWithLowerCamelCaseStrategy() throws Exception {
EnumFlavorA result = MAPPER.readValue(q("saltedCaramel"), EnumFlavorA.class);
assertEquals(EnumFlavorA.SALTED_CARAMEL, result);
String resultString = MAPPER.writeValueAsString(result);
assertEquals(q("saltedCaramel"), resultString);
}
@Test
public void testEnumNamingTranslateUnknownValueToDefault() throws Exception {
EnumFlavorA result = MAPPER.readerFor(EnumFlavorA.class)
.with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)
.readValue(q("__salted_caramel"));
assertEquals(EnumFlavorA.VANILLA, result);
}
@Test
public void testEnumNamingToDefaultNumber() throws Exception {
EnumFlavorA result = MAPPER.readerFor(EnumFlavorA.class)
.without(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)
.readValue(q("1"));
assertEquals(EnumFlavorA.SALTED_CARAMEL, result);
}
@Test
public void testEnumNamingToDefaultEmptyString() throws Exception {
EnumFlavorA result = MAPPER.readerFor(EnumFlavorA.class)
.with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)
.readValue(q(""));
assertEquals(EnumFlavorA.VANILLA, result);
}
@Test
public void testOriginalEnamValueShouldNotBeFoundWithEnumNamingStrategy() throws Exception {
EnumFlavorB result = MAPPER.readerFor(EnumFlavorB.class)
.with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
.readValue(q("PEANUT_BUTTER"));
assertNull(result);
}
@Test
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);
}
@Test
public void testEnumNamingStrategySymmetryReadThenWrite() throws Exception {
EnumSauceC result = MAPPER.readValue(q("ketchUp"), EnumSauceC.class);
assertEquals(EnumSauceC.KETCH_UP, result);
String resultString = MAPPER.writeValueAsString(result);
assertEquals(q("ketchUp"), resultString);
}
@Test
public void testEnumNamingStrategySymmetryWriteThenRead() throws Exception {
String resultString = MAPPER.writeValueAsString(EnumSauceC.MAYO_NEZZ);
EnumSauceC result = MAPPER.readValue(resultString, EnumSauceC.class);
assertEquals(EnumSauceC.MAYO_NEZZ, result);
}
@Test
public void testReadWrapperValueWithEnumNamingStrategy() throws Exception {
String json = "{\"sauce\": \"ketchUp\"}";
EnumSauceWrapperBean wrapper = MAPPER.readValue(json, EnumSauceWrapperBean.class);
assertEquals(EnumSauceC.KETCH_UP, wrapper.sauce);
}
@Test
public void testReadWrapperValueWithCaseInsensitiveEnumNamingStrategy() throws Exception {
ObjectReader reader = MAPPER_CI
.readerFor(EnumSauceWrapperBean.class);
EnumSauceWrapperBean lowerCase = reader.readValue(a2q("{'sauce': 'ketchup'}"));
assertEquals(EnumSauceC.KETCH_UP, lowerCase.sauce);
EnumSauceWrapperBean upperCase = reader.readValue(a2q("{'sauce': 'KETCHUP'}"));
assertEquals(EnumSauceC.KETCH_UP, upperCase.sauce);
EnumSauceWrapperBean mixedCase = reader.readValue(a2q("{'sauce': 'kEtChUp'}"));
assertEquals(EnumSauceC.KETCH_UP, mixedCase.sauce);
}
@Test
public void testWriteThenReadWrapperValueWithEnumNamingStrategy() throws Exception {
EnumSauceWrapperBean sauceWrapper = new EnumSauceWrapperBean(EnumSauceC.MAYO_NEZZ);
String json = MAPPER.writeValueAsString(sauceWrapper);
EnumSauceWrapperBean wrapper = MAPPER.readValue(json, EnumSauceWrapperBean.class);
assertEquals(EnumSauceC.MAYO_NEZZ, wrapper.sauce);
}
@Test
public void testEnumNamingStrategyInterfaceIsNotApplied() throws Exception {
EnumSauceD sauce = MAPPER.readValue(q("SRIRACHA_MAYO"), EnumSauceD.class);
assertEquals(EnumSauceD.SRIRACHA_MAYO, sauce);
}
@Test
public void testEnumNamingStrategyConflictWithUnderScores() throws Exception {
EnumFlavorE flavor = MAPPER.readValue(q("peanutButter"), EnumFlavorE.class);
assertEquals(EnumFlavorE.PEANUT__BUTTER, flavor);
}
@Test
public void testCaseSensensitiveEnumMapKey() throws Exception {
String jsonStr = a2q("{'map':{'ketchUp':'val'}}");
ClassWithEnumMapSauceKey result = MAPPER.readValue(jsonStr, ClassWithEnumMapSauceKey.class);
assertEquals(1, result.map.size());
assertEquals("val", result.map.get(EnumSauceC.KETCH_UP));
}
@Test
public void testAllowCaseInsensensitiveEnumMapKey() throws Exception {
ObjectReader reader = MAPPER_CI
.readerFor(ClassWithEnumMapSauceKey.class);
ClassWithEnumMapSauceKey result = reader.readValue(a2q("{'map':{'KeTcHuP':'val'}}"));
assertEquals(1, result.map.size());
assertEquals("val", result.map.get(EnumSauceC.KETCH_UP));
}
@Test
public void testAllowCaseSensensitiveEnumMapValue() throws Exception {
ObjectReader reader = MAPPER_CI
.readerFor(ClassWithEnumMapSauceValue.class);
ClassWithEnumMapSauceValue result = reader.readValue(
a2q("{'map':{'lowerSauce':'ketchUp', 'upperSauce':'mayoNezz'}}"));
assertEquals(2, result.map.size());
assertEquals(EnumSauceC.KETCH_UP, result.map.get("lowerSauce"));
assertEquals(EnumSauceC.MAYO_NEZZ, result.map.get("upperSauce"));
}
@Test
public void testAllowCaseInsensensitiveEnumMapValue() throws Exception {
ObjectReader reader = MAPPER_CI
.readerFor(ClassWithEnumMapSauceValue.class);
ClassWithEnumMapSauceValue result = reader.readValue(
a2q("{'map':{'lowerSauce':'ketchup', 'upperSauce':'MAYONEZZ'}}"));
assertEquals(2, result.map.size());
assertEquals(EnumSauceC.KETCH_UP, result.map.get("lowerSauce"));
assertEquals(EnumSauceC.MAYO_NEZZ, result.map.get("upperSauce"));
}
@Test
public void testEnumMixInDeserializationTest() throws Exception {
ObjectMapper mapper = jsonMapperBuilder()
.addMixIn(BaseEnum.class, MixInEnum.class)
.build();
// serialization
String ser = mapper.writeValueAsString(BaseEnum.REAL_NAME);
assertEquals(q("realName"), ser);
// deserialization
BaseEnum deser = mapper.readValue(q("realName"), BaseEnum.class);
assertEquals(BaseEnum.REAL_NAME, deser);
}
@Test
void testUseEnumMappingStrategySetInMapper() throws Exception {
ObjectMapper mapper = jsonMapperBuilder()
.enumNamingStrategy(EnumNamingStrategies.LowerCamelCaseStrategy.INSTANCE)
.build();
BaseEnum result = mapper.readValue(q("realName"), BaseEnum.class);
assertEquals(BaseEnum.REAL_NAME, result);
String resultString = mapper.writeValueAsString(result);
assertEquals(q("realName"), resultString);
}
}