package com.fasterxml.jackson.databind.deser.jdk;
import java.io.IOException;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
public class EnumDefaultReadTest extends BaseMapTest
{
enum SimpleEnum {
ZERO,
ONE;
}
enum SimpleEnumWithDefault {
@JsonEnumDefaultValue
ZERO,
ONE;
}
enum CustomEnum {
ZERO(0),
ONE(1);
private final int number;
CustomEnum(final int number) {
this.number = number;
}
@JsonValue
int getNumber() {
return this.number;
}
}
enum CustomEnumWithDefault {
@JsonEnumDefaultValue
ZERO(0),
ONE(1);
private final int number;
CustomEnumWithDefault(final int number) {
this.number = number;
}
@JsonValue
int getNumber() {
return this.number;
}
}
/*
/**********************************************************
/* Test methods
/**********************************************************
*/
private final ObjectMapper MAPPER = new ObjectMapper();
public void testWithoutCustomFeatures() throws Exception
{
final ObjectReader r = MAPPER.reader();
_verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
_verifyOkDeserialization(r, "0", SimpleEnum.class, SimpleEnum.ZERO);
_verifyOkDeserialization(r, "1", SimpleEnum.class, SimpleEnum.ONE);
_verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
_verifyFailingDeserialization(r, "2", SimpleEnum.class);
_verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
_verifyFailingDeserialization(r, "TWO", SimpleEnumWithDefault.class);
_verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
_verifyFailingDeserialization(r, "2", SimpleEnumWithDefault.class);
_verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
_verifyFailingDeserialization(r, "ONE", CustomEnum.class);
_verifyFailingDeserialization(r, "TWO", CustomEnum.class);
_verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
_verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
_verifyFailingDeserialization(r, "2", CustomEnum.class);
_verifyFailingDeserialization(r, "ZERO", CustomEnumWithDefault.class);
_verifyFailingDeserialization(r, "ONE", CustomEnumWithDefault.class);
_verifyFailingDeserialization(r, "TWO", CustomEnumWithDefault.class);
_verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
_verifyFailingDeserialization(r, "2", CustomEnumWithDefault.class);
}
public void testWithFailOnNumbers() throws Exception
{
ObjectReader r = MAPPER.reader()
.with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
_verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
_verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
_verifyFailingDeserialization(r, "0", SimpleEnum.class);
_verifyFailingDeserialization(r, "1", SimpleEnum.class);
_verifyFailingDeserialization(r, "2", SimpleEnum.class);
_verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
_verifyFailingDeserialization(r, "TWO", SimpleEnumWithDefault.class);
_verifyFailingDeserialization(r, "0", SimpleEnumWithDefault.class);
_verifyFailingDeserialization(r, "1", SimpleEnumWithDefault.class);
_verifyFailingDeserialization(r, "2", SimpleEnumWithDefault.class);
_verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
_verifyFailingDeserialization(r, "ONE", CustomEnum.class);
_verifyFailingDeserialization(r, "TWO", CustomEnum.class);
_verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
_verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
_verifyFailingDeserialization(r, "2", CustomEnum.class);
_verifyFailingDeserialization(r, "ZERO", CustomEnumWithDefault.class);
_verifyFailingDeserialization(r, "ONE", CustomEnumWithDefault.class);
_verifyFailingDeserialization(r, "TWO", CustomEnumWithDefault.class);
_verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
_verifyFailingDeserialization(r, "2", CustomEnumWithDefault.class);
}
public void testWithReadUnknownAsDefault() throws Exception
{
ObjectReader r = MAPPER.reader()
.with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
_verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
_verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
_verifyOkDeserialization(r, "0", SimpleEnum.class, SimpleEnum.ZERO);
_verifyOkDeserialization(r, "1", SimpleEnum.class, SimpleEnum.ONE);
_verifyFailingDeserialization(r, "2", SimpleEnum.class);
_verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
_verifyOkDeserialization(r, "TWO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
_verifyOkDeserialization(r, "2", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
_verifyFailingDeserialization(r, "ONE", CustomEnum.class);
_verifyFailingDeserialization(r, "TWO", CustomEnum.class);
_verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
_verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
_verifyFailingDeserialization(r, "2", CustomEnum.class);
_verifyOkDeserialization(r, "ZERO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "ONE", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "TWO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
_verifyOkDeserialization(r, "2", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
}
public void testWithFailOnNumbersAndReadUnknownAsDefault()
throws Exception
{
ObjectReader r = MAPPER.reader()
.with(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)
.with(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
_verifyOkDeserialization(r, "ZERO", SimpleEnum.class, SimpleEnum.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnum.class, SimpleEnum.ONE);
_verifyFailingDeserialization(r, "TWO", SimpleEnum.class);
_verifyFailingDeserialization(r, "0", SimpleEnum.class);
_verifyFailingDeserialization(r, "1", SimpleEnum.class);
_verifyFailingDeserialization(r, "2", SimpleEnum.class);
_verifyOkDeserialization(r, "ZERO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "ONE", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ONE);
_verifyOkDeserialization(r, "TWO", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyFailingDeserialization(r, "ZERO", CustomEnum.class);
_verifyFailingDeserialization(r, "ONE", CustomEnum.class);
_verifyFailingDeserialization(r, "TWO", CustomEnum.class);
_verifyOkDeserialization(r, "0", CustomEnum.class, CustomEnum.ZERO);
_verifyOkDeserialization(r, "1", CustomEnum.class, CustomEnum.ONE);
_verifyFailingDeserialization(r, "2", CustomEnum.class);
_verifyOkDeserialization(r, "ZERO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "ONE", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "TWO", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "0", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", CustomEnumWithDefault.class, CustomEnumWithDefault.ONE);
//
// The three tests below fail; Jackson throws an exception on the basis that
// "FAIL_ON_NUMBERS_FOR_ENUMS" is enabled. I claim the default value should be returned instead.
_verifyOkDeserialization(r, "0", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "1", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
_verifyOkDeserialization(r, "2", SimpleEnumWithDefault.class, SimpleEnumWithDefault.ZERO);
// Fails. Jackson throws an exception on the basis that "FAIL_ON_NUMBERS_FOR_ENUMS"
// is enabled, but the default value should have been returned instead.
_verifyOkDeserialization(r, "2", CustomEnumWithDefault.class, CustomEnumWithDefault.ZERO);
}
private <T> void _verifyOkDeserialization(ObjectReader reader, String fromValue,
Class<T> toValueType, T expValue)
throws IOException
{
assertEquals(expValue, reader.forType(toValueType).readValue(quote(fromValue)));
}
private <T> void _verifyFailingDeserialization(final ObjectReader reader,
final String fromValue, final Class<T> toValueType)
throws IOException
{
try {
reader.forType(toValueType).readValue(quote(fromValue));
fail("Deserialization should have failed");
} catch (InvalidFormatException e) {
verifyException(e, "Can not deserialize value of type");
/* Expected. */
}
}
}