Skip to content
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 @@ -8,6 +8,7 @@ public class SerializationConfig {
private boolean shouldIgnoreAnySetterAnnotation;
private boolean shouldDisableReadUnknownEnumValuesAsDefaultValue;
private boolean shouldUseSnakeCase;
private boolean shouldAllowNullAsDefaultValueForReadUnknownEnums;

public SerializationConfig() {
mixins = new HashMap<>();
Expand Down Expand Up @@ -36,6 +37,11 @@ public SerializationConfig setShouldUseSnakeCase() {
return this;
}

public SerializationConfig setShouldAllowNullAsDefaultValueForReadUnknownEnums() {
this.shouldAllowNullAsDefaultValueForReadUnknownEnums = true;
return this;
}

public Map<Class<?>, Class<?>> getMixins() {
return mixins;
}
Expand All @@ -50,12 +56,19 @@ public boolean shouldUseSnakeCase() {
return shouldUseSnakeCase;
}

public boolean shouldAllowNullAsDefaultValueForReadUnknownEnums() {
return shouldAllowNullAsDefaultValueForReadUnknownEnums;
}


@Override
public String toString() {
return "SerializationConfig{" +
"mixins=" + mixins +
", shouldIgnoreAnySetterAnnotation=" + shouldIgnoreAnySetterAnnotation +
", shouldDisableReadUnknownEnumValuesAsDefaultValue=" + shouldDisableReadUnknownEnumValuesAsDefaultValue +
", shouldUseSnakeCase=" + shouldUseSnakeCase +
", shouldAllowNullAsDefaultValueForReadUnknownEnums=" + shouldAllowNullAsDefaultValueForReadUnknownEnums +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public static ObjectMapper createObjectMapper(SerializationConfig serializationC
if (!serializationConfig.shouldDisableReadUnknownEnumValuesAsDefaultValue()) {
objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true);
}
if (serializationConfig.shouldAllowNullAsDefaultValueForReadUnknownEnums()) {
// NOTE: default enum value takes precedence over null
objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
}

serializationConfig.getMixins().forEach(objectMapper::addMixIn);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,36 @@ public void createObjectMapper_defaultSerializationConfigAndApiObjectHasInvalidE
Assert.assertEquals("Unknown enum is parsed incorrectly", SampleEnum.UNKNOWN, sampleApi.letter);
}

@Test
public void createObjectMapper_serializationConfigAndAllowNullAsDefaultValueForReadUnknownEnumsAndApiObjectHasInvalidEnum_defaultValueUsedOnSerialization() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig().setShouldAllowNullAsDefaultValueForReadUnknownEnums();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letter\": \"D\" }", SampleApi.class);

Assert.assertEquals("Unknown enum is parsed incorrectly. Default takes precedence before null", SampleEnum.UNKNOWN, sampleApi.letter);
}

@Test
public void createObjectMapper_defaultSerializationConfigAndApiObjectHasEmptyEnumValue_defaultValueUsedOnSerialization() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letter\": \"D\" }", SampleApi.class);
SampleApi sampleApi = objectMapper.readValue("{ \"letter\": \"\" }", SampleApi.class);

Assert.assertEquals("Unknown enum is parsed incorrectly", SampleEnum.UNKNOWN, sampleApi.letter);
}

@Test
public void createObjectMapper_defaultSerializationConfigAndApiObjectHasNullEnumValue_nullOnSerialization() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letter\": null }", SampleApi.class);

Assert.assertNull("Unknown enum is parsed incorrectly", sampleApi.letter);
}

@Test
public void createObjectMapper_serializationConfigWithReadUnknownEnumsDisabledAndApiObjectHasValidEnum_enumParsedCorrectly() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig().setShouldDisableReadUnknownEnumValuesAsDefaultValue();
Expand All @@ -118,6 +138,16 @@ public void createObjectMapper_serializationConfigWithReadUnknownEnumsDisabledAn
objectMapper.readValue("{ \"letter\": \"D\" }", SampleApi.class);
}

@Test
public void createObjectMapper_serializationConfigWithReadUnknownEnumsDisabledAndAllowNullAsDefaultValueForReadUnknownEnumsAndApiObjectHasInvalidEnum_nullOnSerialization() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig().setShouldDisableReadUnknownEnumValuesAsDefaultValue().setShouldAllowNullAsDefaultValueForReadUnknownEnums();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letter\": \"D\" }", SampleApi.class);

Assert.assertNull("Unknown enum is parsed incorrectly", sampleApi.letter);
}

@Test(expected = InvalidFormatException.class)
public void createObjectMapper_serializationConfigWithReadUnknownEnumsDisabledAndApiObjectHasEmptyEnumValue_InvalidFormatExceptionIsThrown() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig().setShouldDisableReadUnknownEnumValuesAsDefaultValue();
Expand All @@ -126,9 +156,70 @@ public void createObjectMapper_serializationConfigWithReadUnknownEnumsDisabledAn
objectMapper.readValue("{ \"letter\": \"\" }", SampleApi.class);
}

@Test
public void createObjectMapper_serializationConfigWithReadUnknownEnumsDisabledAndAllowNullAsDefaultValueForReadUnknownEnumsAndApiObjectHasEmptyEnumValue_nullOnSerialization() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig().setShouldDisableReadUnknownEnumValuesAsDefaultValue().setShouldAllowNullAsDefaultValueForReadUnknownEnums();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letter\": \"\" }", SampleApi.class);

Assert.assertNull("Unknown enum is parsed incorrectly", sampleApi.letter);
}

@Test
public void createObjectMapper_defaultSerializationConfigAndNoDefaultEnumIsValid_enumParsedCorrectly() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letterNoDefault\": \"BB\" }", SampleApi.class);

Assert.assertEquals("shouldAllowNullAsDefaultValueForReadUnknownEnums should not affect deserializing valid enums",
SampleEnumNoDefault.BB, sampleApi.letterNoDefault);
}

@Test
public void createObjectMapper_defaultSerializationConfigAndNoDefaultEnumIsNull_enumIsNull() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letterNoDefault\": null }", SampleApi.class);

Assert.assertNull("shouldAllowNullAsDefaultValueForReadUnknownEnums should not affect deserializing null enums", sampleApi.letterNoDefault);
}

@Test(expected = InvalidFormatException.class)
public void createObjectMapper_defaultSerializationConfigAndNoDefaultEnumIsEmpty_InvalidFormatExceptionIsThrown() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

objectMapper.readValue("{ \"letterNoDefault\": \"\" }", SampleApi.class);
}

@Test(expected = InvalidFormatException.class)
public void createObjectMapper_defaultSerializationConfigAndNoDefaultEnumIsInvalid_InvalidFormatExceptionIsThrown() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

objectMapper.readValue("{ \"letterNoDefault\": \"BBB\" }", SampleApi.class);
}

@Test
public void createObjectMapper_serializationConfigAndAllowNullAsDefaultValueForReadUnknownEnumsAndNoDefaultEnumIsInvalid_enumIsNull() throws IOException {
SerializationConfig serializationConfig = new SerializationConfig().setShouldAllowNullAsDefaultValueForReadUnknownEnums();
ObjectMapper objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);

SampleApi sampleApi = objectMapper.readValue("{ \"letterNoDefault\": \"BBB\" }", SampleApi.class);

Assert.assertNull("Even though enum has no set default value and deserialization not configured to use default value, null should be default",
sampleApi.letterNoDefault);
}

private enum SampleEnum {
A, B, @JsonEnumDefaultValue UNKNOWN
}
private enum SampleEnumNoDefault {
AA, BB
}

private static class SampleApi {
@JsonProperty("id")
Expand All @@ -137,6 +228,9 @@ private static class SampleApi {
@JsonProperty("letter")
SampleEnum letter;

@JsonProperty("letterNoDefault")
SampleEnumNoDefault letterNoDefault;

@JsonProperty("name")
String name;

Expand Down