diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializer5165Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializer5165Test.java new file mode 100644 index 0000000000..b4e9b03c85 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializer5165Test.java @@ -0,0 +1,63 @@ +package com.fasterxml.jackson.databind.deser.jdk; + +import java.util.EnumMap; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidNullException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.opentest4j.AssertionFailedError; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// For [databind#5165] +public class EnumMapDeserializer5165Test +{ + public enum MyEnum { + FOO + } + + static class Dst { + private EnumMap map; + + public EnumMap getMap() { + return map; + } + + public void setMap(EnumMap map) { + this.map = map; + } + } + + @Test + public void nullsFailTest() { + ObjectMapper mapper = JsonMapper.builder() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)) + .build(); + + assertThrows( + AssertionFailedError.class, + () -> assertThrows( + InvalidNullException.class, + () -> mapper.readValue("{\"map\":{\"FOO\":\"\"}}", new TypeReference(){}) + ), + "databind#5165 for EnumMapDeserializer is fixed" + ); + } + + @Test + public void nullsSkipTest() throws Exception { + ObjectMapper mapper = JsonMapper.builder() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) + .build(); + + Dst dst = mapper.readValue("{\"map\":{\"FOO\":\"\"}}", new TypeReference() {}); + + assertFalse(dst.getMap().isEmpty(), "databind#5165 for EnumMapDeserializer is fixed"); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumSetDeserializer5165Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumSetDeserializer5165Test.java new file mode 100644 index 0000000000..3b7eaf2833 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumSetDeserializer5165Test.java @@ -0,0 +1,98 @@ +package com.fasterxml.jackson.databind.deser.jdk; + +import java.io.IOException; +import java.util.EnumSet; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.exc.InvalidNullException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.opentest4j.AssertionFailedError; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// For [databind#5165] +public class EnumSetDeserializer5165Test +{ + public enum MyEnum { + FOO + } + + static class Dst { + private EnumSet set; + + public EnumSet getSet() { + return set; + } + + public void setSet(EnumSet set) { + this.set = set; + } + } + + // Custom deserializer that converts empty strings to null + static class EmptyStringToNullDeserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public EmptyStringToNullDeserializer() { + super(MyEnum.class); + } + + @Override + public MyEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + String value = p.getValueAsString(); + if (value != null && value.isEmpty()) { + return null; + } + return MyEnum.valueOf(value); + } + } + + private ObjectMapper createMapperWithCustomDeserializer() { + SimpleModule module = new SimpleModule(); + module.addDeserializer(MyEnum.class, new EmptyStringToNullDeserializer()); + + return JsonMapper.builder() + .addModule(module) + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)) + .build(); + } + + @Test + public void nullsFailTest() { + ObjectMapper mapper = createMapperWithCustomDeserializer(); + + assertThrows( + AssertionFailedError.class, + () -> assertThrows( + InvalidNullException.class, + () -> mapper.readValue("{\"set\":[\"\"]}", new TypeReference(){}) + ), + "databind#5165 for EnumSetDeserializer is fixed" + ); + } + + @Test + public void nullsSkipTest() throws Exception { + SimpleModule module = new SimpleModule(); + module.addDeserializer(MyEnum.class, new EmptyStringToNullDeserializer()); + + ObjectMapper mapper = JsonMapper.builder() + .addModule(module) + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) + .build(); + + Dst dst = mapper.readValue("{\"set\":[\"FOO\",\"\"]}", new TypeReference() {}); + + assertFalse(dst.getSet().isEmpty(), "databind#5165 for EnumSetDeserializer is fixed"); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializer5165Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializer5165Test.java new file mode 100644 index 0000000000..415804cd8d --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializer5165Test.java @@ -0,0 +1,59 @@ +package com.fasterxml.jackson.databind.deser.jdk; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidNullException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.opentest4j.AssertionFailedError; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// For [databind#5165] +public class MapDeserializer5165Test +{ + static class Dst { + private Map map; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + } + + @Test + public void nullsFailTest() { + ObjectMapper mapper = JsonMapper.builder() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)) + .build(); + + assertThrows( + AssertionFailedError.class, + () -> assertThrows( + InvalidNullException.class, + () -> mapper.readValue("{\"map\":{\"key\":\"\"}}", new TypeReference(){}) + ), + "databind#5165 for MapDeserializer is fixed" + ); + } + + @Test + public void nullsSkipTest() throws Exception { + ObjectMapper mapper = JsonMapper.builder() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) + .build(); + + Dst dst = mapper.readValue("{\"map\":{\"key\":\"\"}}", new TypeReference() {}); + + assertFalse(dst.getMap().isEmpty(), "databind#5165 for MapDeserializer is fixed"); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/ObjectArrayDeserializer5165Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/ObjectArrayDeserializer5165Test.java new file mode 100644 index 0000000000..c23db14a3d --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/ObjectArrayDeserializer5165Test.java @@ -0,0 +1,57 @@ +package com.fasterxml.jackson.databind.deser.jdk; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidNullException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import org.opentest4j.AssertionFailedError; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// For [databind#5165] +public class ObjectArrayDeserializer5165Test +{ + static class Dst { + private Integer[] array; + + public Integer[] getArray() { + return array; + } + + public void setArray(Integer[] array) { + this.array = array; + } + } + + @Test + public void nullsFailTest() { + ObjectMapper mapper = JsonMapper.builder() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)) + .build(); + + assertThrows( + AssertionFailedError.class, + () -> assertThrows( + InvalidNullException.class, + () -> mapper.readValue("{\"array\":[\"\"]}", new TypeReference(){}) + ), + "databind#5165 for ObjectArrayDeserializer is fixed" + ); + } + + @Test + public void nullsSkipTest() throws Exception { + ObjectMapper mapper = JsonMapper.builder() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) + .build(); + + Dst dst = mapper.readValue("{\"array\":[\"\"]}", new TypeReference() {}); + + assertFalse(dst.getArray() == null || dst.getArray().length == 0, "databind#5165 for ObjectArrayDeserializer is fixed"); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/StringArrayDeserializer5165Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/StringArrayDeserializer5165Test.java new file mode 100644 index 0000000000..8bbdf220a0 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/StringArrayDeserializer5165Test.java @@ -0,0 +1,93 @@ +package com.fasterxml.jackson.databind.deser.jdk; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.exc.InvalidNullException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.opentest4j.AssertionFailedError; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// For [databind#5165] +public class StringArrayDeserializer5165Test +{ + static class Dst { + private String[] array; + + public String[] getArray() { + return array; + } + + public void setArray(String[] array) { + this.array = array; + } + } + + // Custom deserializer that converts empty strings to null + static class EmptyStringToNullDeserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public EmptyStringToNullDeserializer() { + super(String.class); + } + + @Override + public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + String value = p.getValueAsString(); + if (value != null && value.isEmpty()) { + return null; + } + return value; + } + } + + private ObjectMapper createMapperWithCustomDeserializer() { + SimpleModule module = new SimpleModule(); + module.addDeserializer(String.class, new EmptyStringToNullDeserializer()); + + return JsonMapper.builder() + .addModule(module) + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)) + .build(); + } + + @Test + public void nullsFailTest() { + ObjectMapper mapper = createMapperWithCustomDeserializer(); + + assertThrows( + AssertionFailedError.class, + () -> assertThrows( + InvalidNullException.class, + () -> mapper.readValue("{\"array\":[\"\"]}", new TypeReference(){}) + ), + "databind#5165 for StringArrayDeserializer is fixed" + ); + } + + @Test + public void nullsSkipTest() throws Exception { + SimpleModule module = new SimpleModule(); + module.addDeserializer(String.class, new EmptyStringToNullDeserializer()); + + ObjectMapper mapper = JsonMapper.builder() + .addModule(module) + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) + .build(); + + Dst dst = mapper.readValue("{\"array\":[\"\"]}", new TypeReference() {}); + + assertFalse(dst.getArray() == null || dst.getArray().length == 0, "databind#5165 for StringArrayDeserializer is fixed"); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/StringCollectionDeserializer5165Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/StringCollectionDeserializer5165Test.java new file mode 100644 index 0000000000..b0aaf8441f --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/StringCollectionDeserializer5165Test.java @@ -0,0 +1,94 @@ +package com.fasterxml.jackson.databind.deser.jdk; + +import java.io.IOException; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.exc.InvalidNullException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.opentest4j.AssertionFailedError; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// For [databind#5165] +public class StringCollectionDeserializer5165Test +{ + static class Dst { + private List list; + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + } + + // Custom deserializer that converts empty strings to null + static class EmptyStringToNullDeserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public EmptyStringToNullDeserializer() { + super(String.class); + } + + @Override + public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + String value = p.getValueAsString(); + if (value != null && value.isEmpty()) { + return null; + } + return value; + } + } + + private ObjectMapper createMapperWithCustomDeserializer() { + SimpleModule module = new SimpleModule(); + module.addDeserializer(String.class, new EmptyStringToNullDeserializer()); + + return JsonMapper.builder() + .addModule(module) + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL)) + .build(); + } + + @Test + public void nullsFailTest() { + ObjectMapper mapper = createMapperWithCustomDeserializer(); + + assertThrows( + AssertionFailedError.class, + () -> assertThrows( + InvalidNullException.class, + () -> mapper.readValue("{\"list\":[\"\"]}", new TypeReference(){}) + ), + "databind#5165 for StringCollectionDeserializer is fixed" + ); + } + + @Test + public void nullsSkipTest() throws Exception { + SimpleModule module = new SimpleModule(); + module.addDeserializer(String.class, new EmptyStringToNullDeserializer()); + + ObjectMapper mapper = JsonMapper.builder() + .addModule(module) + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP)) + .build(); + + Dst dst = mapper.readValue("{\"list\":[\"\"]}", new TypeReference() {}); + + assertFalse(dst.getList().isEmpty(), "databind#5165 for StringCollectionDeserializer is fixed"); + } +}