Skip to content

Commit

Permalink
Fixed #3214 (I hope ;) )
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Sep 1, 2021
1 parent 4a006dd commit bd41ee2
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 14 deletions.
3 changes: 3 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ Project: jackson-databind
(contributed by Klaas D)
#3193: Add `MapperFeature.APPLY_DEFAULT_VALUES`, initially for Scala module
(suggested by Nick B)
#3214: For an absent property Jackson injects `NullNode` instead of `null` to a
JsonNode-typed constructor argument of a `@ConstructorProperties`-annotated constructor
(repored by robvarga@github)
#3217: `XMLGregorianCalendar` doesn't work with default typing
(reported by Xinzhe Y)
#3227: Content `null` handling not working for root values
Expand Down
27 changes: 25 additions & 2 deletions src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,9 @@ public T getNullValue(DeserializationContext ctxt) throws JsonMappingException {
* to be called just once (static values), or each time empty value is
* needed.
*<p>
* Default implementation indicates that "null value" to use for input null
* is simply Java `null` for all deserializers, unless overridden by sub-classes.
* Default implementation indicates that the "null value" to use for input null
* does not vary across uses so that {@link #getNullValue(DeserializationContext)}
* need not be called more than once per deserializer instance.
* This information may be used as optimization.
*/
@Override
Expand All @@ -327,6 +328,28 @@ public AccessPattern getNullAccessPattern() {
return AccessPattern.CONSTANT;
}

/**
* Method called to determine placeholder value to be used for cases
* where no value was obtained from input but we must pass a value
* nonetheless: the common case is that of Creator methods requiring
* passing a value for every parameter.
* Usually this is same as {@link #getNullValue} (which in turn
* is usually simply Java {@code null}), but it can be overridden
* for specific types: most notable scalar types must use "default"
* values.
*<p>
* This method needs to be called every time a determination is made.
*<p>
* Default implementation simply calls {@link #getNullValue} and
* returns value.
*
* @since 2.13
*/
@Override
public Object getAbsentValue(DeserializationContext ctxt) throws JsonMappingException {
return getNullValue(ctxt);
}

/*
/**********************************************************
/* Accessors for other replacement/placeholder values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,24 @@ public interface NullValueProvider
* access null replacement value.
*/
public AccessPattern getNullAccessPattern();

/**
* Method called to determine placeholder value to be used for cases
* where no value was obtained from input but we must pass a value
* nonetheless: the common case is that of Creator methods requiring
* passing a value for every parameter.
* Usually this is same as {@link #getNullValue} (which in turn
* is usually simply Java {@code null}), but it can be overridden
* for specific types: most notable scalar types must use "default"
* values.
*<p>
* This method needs to be called every time a determination is made.
*<p>
* Default implementation simply calls and returns {@link #getNullValue}.
*
* @since 2.13
*/
default Object getAbsentValue(DeserializationContext ctxt) throws JsonMappingException {
return getNullValue(ctxt);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
import java.util.BitSet;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.SettableAnyProperty;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
Expand Down Expand Up @@ -202,14 +199,15 @@ protected Object _findMissing(SettableBeanProperty prop) throws JsonMappingExcep
}
try {
// Third: NullValueProvider? (22-Sep-2019, [databind#2458])
Object nullValue = prop.getNullValueProvider().getNullValue(_context);
if (nullValue != null) {
return nullValue;
// 08-Aug-2021, tatu: consider [databind#3214]; not null but "absent" value...
Object absentValue = prop.getNullValueProvider().getAbsentValue(_context);
if (absentValue != null) {
return absentValue;
}

// Fourth: default value
JsonDeserializer<Object> deser = prop.getValueDeserializer();
return deser.getNullValue(_context);
return deser.getAbsentValue(_context);
} catch (DatabindException e) {
// [databind#2101]: Include property name, if we have it
AnnotatedMember member = prop.getMember();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public JsonNode getNullValue(DeserializationContext ctxt) {
return ctxt.getNodeFactory().nullNode();
}

/**
* Overridden variant to ensure that absent values are NOT coerced into
* {@code NullNode}s, unlike incoming {@code null} values.
*/
@Override // since 2.13
public Object getAbsentValue(DeserializationContext ctxt) {
return null;
}

/**
* Implementation that will produce types of any JSON nodes; not just one
* deserializer is registered to handle (in case of more specialized handler).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.fasterxml.jackson.failing;
package com.fasterxml.jackson.databind.node;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.TextNode;

public class NullJsonNodeViaCreator3214Test extends BaseMapTest
public class AbsentNodeViaCreator3214Test extends BaseMapTest
{
static class Pojo3214
{
Expand Down

0 comments on commit bd41ee2

Please sign in to comment.