diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index d191f278aa..7af3dee2de 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -837,3 +837,8 @@ Joffrey Bion (joffrey-bion@github) Christoph (cfiehe@github.com) * Contributed #2299: Fix for using jackson-databind in an OSGi environment under Android (2.9.9) + +Cyril Martin (mcoolive@github.com) + * Reported #2303: Deserialize null, when java type is "TypeRef of TypeRef of T", + does not provide "Type(Type(null))" + (2.9.9) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 54779ad04d..720082a718 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -16,6 +16,8 @@ Project: jackson-databind (reported by Joffrey B) #2299: Fix for using jackson-databind in an OSGi environment under Android (contributed by Christoph F) +#2303: Deserialize null, when java type is "TypeRef of TypeRef of T", does not provide "Type(Type(null))" + (reported by Cyril M) - Prevent String coercion of `null` in `WritableObjectId` when calling `JsonGenerator.writeObjectId()`, mostly relevant for formats like YAML that have native Object Ids diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java index 2d42a8157f..f9badf80a9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java @@ -131,7 +131,9 @@ public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } - return new CreatorProperty(this, deser, _nullProvider); + // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were + NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider; + return new CreatorProperty(this, deser, nvp); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java index d8b38bb025..973c85b54f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java @@ -89,7 +89,9 @@ public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } - return new FieldProperty(this, deser, _nullProvider); + // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were + NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider; + return new FieldProperty(this, deser, nvp); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java index aeeeba6b73..08111d4b43 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/MethodProperty.java @@ -80,7 +80,9 @@ public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } - return new MethodProperty(this, deser, _nullProvider); + // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were + NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider; + return new MethodProperty(this, deser, nvp); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java index f1b62ab635..449cc79900 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdReferenceProperty.java @@ -50,7 +50,9 @@ public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } - return new ObjectIdReferenceProperty(this, deser, _nullProvider); + // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were + NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider; + return new ObjectIdReferenceProperty(this, deser, nvp); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java index 6316e280a4..7fe91fcf13 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ObjectIdValueProperty.java @@ -51,7 +51,9 @@ public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } - return new ObjectIdValueProperty(this, deser, _nullProvider); + // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were + NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider; + return new ObjectIdValueProperty(this, deser, nvp); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java index 2ce045b64a..a901f079ff 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java @@ -64,7 +64,9 @@ public SettableBeanProperty withValueDeserializer(JsonDeserializer deser) { if (_valueDeserializer == deser) { return this; } - return new SetterlessProperty(this, deser, _nullProvider); + // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were + NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider; + return new SetterlessProperty(this, deser, nvp); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java index 916e266ef6..486106c655 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java @@ -37,9 +37,10 @@ public AtomicReferenceDeserializer withResolved(TypeDeserializer typeDeser, Json return new AtomicReferenceDeserializer(_fullType, _valueInstantiator, typeDeser, valueDeser); } + @Override - public AtomicReference getNullValue(DeserializationContext ctxt) { - return new AtomicReference(); + public AtomicReference getNullValue(DeserializationContext ctxt) throws JsonMappingException { + return new AtomicReference(_valueDeserializer.getNullValue(ctxt)); } @Override diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java index 56bf081b61..34e502d0e8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java @@ -118,10 +118,10 @@ protected abstract ReferenceTypeDeserializer withResolved(TypeDeserializer ty JsonDeserializer valueDeser); @Override - public abstract T getNullValue(DeserializationContext ctxt); + public abstract T getNullValue(DeserializationContext ctxt) throws JsonMappingException; @Override - public Object getEmptyValue(DeserializationContext ctxt) { + public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return getNullValue(ctxt); } diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKAtomicTypesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKAtomicTypesDeserTest.java similarity index 91% rename from src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKAtomicTypesTest.java rename to src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKAtomicTypesDeserTest.java index 5721556593..40b5a45352 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKAtomicTypesTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKAtomicTypesDeserTest.java @@ -6,10 +6,11 @@ import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -public class JDKAtomicTypesTest +public class JDKAtomicTypesDeserTest extends com.fasterxml.jackson.databind.BaseMapTest { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) @@ -93,6 +94,11 @@ static class Issue1256Bean { public AtomicReference b = new AtomicReference(); } + // [databind#2303] + static class MyBean2303 { + public AtomicReference> refRef; + } + /* /********************************************************** /* Test methods @@ -271,11 +277,25 @@ public void testEmpty1256() throws Exception @SuppressWarnings("unchecked") public void testNullValueHandling() throws Exception { - ObjectMapper mapper = new ObjectMapper(); AtomicReference inputData = new AtomicReference(); - String json = mapper.writeValueAsString(inputData); - AtomicReference readData = (AtomicReference) mapper.readValue(json, AtomicReference.class); + String json = MAPPER.writeValueAsString(inputData); + AtomicReference readData = (AtomicReference) MAPPER.readValue(json, AtomicReference.class); assertNotNull(readData); assertNull(readData.get()); } + + // [databind#2303] + public void testNullWithinNested() throws Exception + { + final ObjectReader r = MAPPER.readerFor(MyBean2303.class); + MyBean2303 intRef = r.readValue(" {\"refRef\": 2 } "); + assertNotNull(intRef.refRef); + assertNotNull(intRef.refRef.get()); + assertEquals(intRef.refRef.get().get(), new Integer(2)); + + MyBean2303 nullRef = r.readValue(" {\"refRef\": null } "); + assertNotNull(nullRef.refRef); + assertNotNull(nullRef.refRef.get()); + assertNull(nullRef.refRef.get().get()); + } }