diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java index 83c3766e28..0a616ed3ea 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java @@ -102,7 +102,7 @@ public Collection deserialize(JsonParser jp, DeserializationContext ctxt Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java index 47bf6648ec..3aa4ec2698 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java @@ -226,7 +226,7 @@ public Collection deserialize(JsonParser jp, DeserializationContext ctxt try { Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { @@ -278,7 +278,7 @@ protected final Collection handleNonArray(JsonParser jp, Deserialization Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java index ae3c52b862..552af529d6 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java @@ -141,7 +141,7 @@ public EnumMap deserialize(JsonParser jp, DeserializationContext ctxt) thro Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java index 7ea12aa450..b2c6ac7427 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java @@ -391,7 +391,7 @@ protected final void _readAndBind(JsonParser jp, DeserializationContext ctxt, // Note: must handle null explicitly here; value deserializers won't Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { @@ -445,7 +445,7 @@ protected final void _readAndBindStringMap(JsonParser jp, DeserializationContext // Note: must handle null explicitly here; value deserializers won't Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { @@ -507,7 +507,7 @@ public Map _deserializeUsingCreator(JsonParser jp, Deserializatio Object key = _keyDeserializer.deserializeKey(fieldName, ctxt); Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = valueDes.getNullValue(); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java index c56d792be7..ed5b264157 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java @@ -144,7 +144,7 @@ public Object[] deserialize(JsonParser jp, DeserializationContext ctxt) Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = _elementDeserializer.getNullValue(); } else if (typeDeser == null) { value = _elementDeserializer.deserialize(jp, ctxt); } else { @@ -225,7 +225,7 @@ private final Object[] handleNonArray(JsonParser jp, DeserializationContext ctxt Object value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = _elementDeserializer.getNullValue(); } else if (_elementTypeDeserializer == null) { value = _elementDeserializer.deserialize(jp, ctxt); } else { diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java index c0757eeb60..fdfeecb2ea 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringArrayDeserializer.java @@ -63,7 +63,7 @@ public String[] deserialize(JsonParser jp, DeserializationContext ctxt) throws I if (t == JsonToken.VALUE_STRING) { value = jp.getText(); } else if (t == JsonToken.VALUE_NULL) { - value = null; + value = _elementDeserializer.getNullValue(); } else { value = _parseString(jp, ctxt); } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java index 754f74af3e..ff0eec236b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java @@ -183,7 +183,7 @@ private Collection deserializeUsingCustom(JsonParser jp, Deserialization String value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = deser.getNullValue(); } else { value = deser.deserialize(jp, ctxt); } @@ -216,7 +216,7 @@ private final Collection handleNonArray(JsonParser jp, DeserializationCo String value; if (t == JsonToken.VALUE_NULL) { - value = null; + value = (valueDes == null) ? null : valueDes.getNullValue(); } else { value = (valueDes == null) ? _parseString(jp, ctxt) : valueDes.deserialize(jp, ctxt); } diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java index 89d684a41e..4dfc3a1476 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestNullHandling.java @@ -1,9 +1,13 @@ package com.fasterxml.jackson.databind.deser; import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -51,4 +55,52 @@ public void testCustomRootNulls() throws Exception assertNotNull(str); assertEquals("funny", str); } + + // Test for [jackson-databind-407] + public void testListOfNulls() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addDeserializer(String.class, new FunnyNullDeserializer()); + mapper.registerModule(module); + + List list = Arrays.asList("funny"); + JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, String.class); + + // should get non-default null directly: + List deser = mapper.readValue("[null]", type); + assertNotNull(deser); + assertEquals(1, deser.size()); + assertEquals(list.get(0), deser.get(0)); + + // as well as via ObjectReader + ObjectReader reader = mapper.reader(type); + deser = reader.readValue("[null]"); + assertNotNull(deser); + assertEquals(1, deser.size()); + assertEquals(list.get(0), deser.get(0)); + } + + // Test for [jackson-databind-407] + public void testMapOfNulls() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addDeserializer(String.class, new FunnyNullDeserializer()); + mapper.registerModule(module); + + JavaType type = mapper.getTypeFactory().constructMapType(Map.class, String.class, String.class); + // should get non-default null directly: + Map deser = mapper.readValue("{\"key\":null}", type); + assertNotNull(deser); + assertEquals(1, deser.size()); + assertEquals("funny", deser.get("key")); + + // as well as via ObjectReader + ObjectReader reader = mapper.reader(type); + deser = mapper.readValue("{\"key\":null}", type); + assertNotNull(deser); + assertEquals(1, deser.size()); + assertEquals("funny", deser.get("key")); + } }