package io.dropwizard.jackson;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import java.sql.ClientInfoStatus;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
public class FuzzyEnumModuleTest {
private final ObjectMapper mapper = new ObjectMapper();
private enum EnumWithLowercase {
lower_case_enum,
mixedCaseEnum
}
private enum EnumWithCreator {
TEST;
@JsonCreator
public static EnumWithCreator fromString(String value) {
return EnumWithCreator.TEST;
}
}
private enum CurrencyCode {
USD("United States dollar"),
AUD("a_u_d"),
CAD("c-a-d"),
BLA("b.l.a"),
EUR("Euro"),
GBP("Pound sterling");
private final String description;
CurrencyCode(String name) {
this.description = name;
}
@Override
public String toString() {
return description;
}
}
enum EnumWithPropertyAnno {
@JsonProperty("a a")
A,
// For this value, force use of anonymous sub-class, to ensure things still work
@JsonProperty("b b")
B {
@Override
public String toString() {
return "bb";
}
},
@JsonProperty("forgot password")
FORGOT_PASSWORD,
}
@Before
public void setUp() throws Exception {
mapper.registerModule(new FuzzyEnumModule());
}
@Test
public void mapsUpperCaseEnums() throws Exception {
assertThat(mapper.readValue("\"SECONDS\"", TimeUnit.class))
.isEqualTo(TimeUnit.SECONDS);
}
@Test
public void mapsLowerCaseEnums() throws Exception {
assertThat(mapper.readValue("\"milliseconds\"", TimeUnit.class))
.isEqualTo(TimeUnit.MILLISECONDS);
}
@Test
public void mapsPaddedEnums() throws Exception {
assertThat(mapper.readValue("\" MINUTES \"", TimeUnit.class))
.isEqualTo(TimeUnit.MINUTES);
}
@Test
public void mapsSpacedEnums() throws Exception {
assertThat(mapper.readValue("\" MILLI SECONDS \"", TimeUnit.class))
.isEqualTo(TimeUnit.MILLISECONDS);
}
@Test
public void mapsDashedEnums() throws Exception {
assertThat(mapper.readValue("\"REASON-UNKNOWN\"", ClientInfoStatus.class))
.isEqualTo(ClientInfoStatus.REASON_UNKNOWN);
}
@Test
public void mapsDottedEnums() throws Exception {
assertThat(mapper.readValue("\"REASON.UNKNOWN\"", ClientInfoStatus.class))
.isEqualTo(ClientInfoStatus.REASON_UNKNOWN);
}
@Test
public void mapsWhenEnumHasCreator() throws Exception {
assertThat(mapper.readValue("\"BLA\"", EnumWithCreator.class))
.isEqualTo(EnumWithCreator.TEST);
}
@Test
public void failsOnIncorrectValue() throws Exception {
try {
mapper.readValue("\"wrong\"", TimeUnit.class);
failBecauseExceptionWasNotThrown(JsonMappingException.class);
} catch (JsonMappingException e) {
assertThat(e.getOriginalMessage())
.isEqualTo("wrong was not one of [NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]");
}
}
@Test
public void mapsToLowerCaseEnums() throws Exception {
assertThat(mapper.readValue("\"lower_case_enum\"", EnumWithLowercase.class))
.isEqualTo(EnumWithLowercase.lower_case_enum);
}
@Test
public void mapsMixedCaseEnums() throws Exception {
assertThat(mapper.readValue("\"mixedCaseEnum\"", EnumWithLowercase.class))
.isEqualTo(EnumWithLowercase.mixedCaseEnum);
}
@Test
public void readsEnumsUsingToString() throws Exception {
final ObjectMapper toStringEnumsMapper = mapper.copy()
.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
assertThat(toStringEnumsMapper.readValue("\"Pound sterling\"", CurrencyCode.class)).isEqualTo(CurrencyCode.GBP);
}
@Test
public void readsEnumsUsingToStringWithDeserializationFeatureOff() throws Exception {
assertThat(mapper.readValue("\"Pound sterling\"", CurrencyCode.class)).isEqualTo(CurrencyCode.GBP);
assertThat(mapper.readValue("\"a_u_d\"", CurrencyCode.class)).isEqualTo(CurrencyCode.AUD);
assertThat(mapper.readValue("\"c-a-d\"", CurrencyCode.class)).isEqualTo(CurrencyCode.CAD);
assertThat(mapper.readValue("\"b.l.a\"", CurrencyCode.class)).isEqualTo(CurrencyCode.BLA);
}
@Test
public void testEnumWithJsonPropertyRename() throws Exception {
final String json = mapper.writeValueAsString(new EnumWithPropertyAnno[] {
EnumWithPropertyAnno.B, EnumWithPropertyAnno.A, EnumWithPropertyAnno.FORGOT_PASSWORD
});
assertThat(json).isEqualTo("[\"b b\",\"a a\",\"forgot password\"]");
final EnumWithPropertyAnno[] result = mapper.readValue(json, EnumWithPropertyAnno[].class);
assertThat(result).isNotNull().hasSize(3);
assertThat(result[0]).isEqualTo(EnumWithPropertyAnno.B);
assertThat(result[1]).isEqualTo(EnumWithPropertyAnno.A);
assertThat(result[2]).isEqualTo(EnumWithPropertyAnno.FORGOT_PASSWORD);
}
}