Skip to content

Fail on null creator properties when deserializing #1193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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 @@ -230,7 +230,20 @@ public enum DeserializationFeature implements ConfigFeature
* @since 2.6
*/
FAIL_ON_MISSING_CREATOR_PROPERTIES(false),


/**
* Feature that determines what happens if one or more Creator properties (properties
* bound to parameters of Creator method (constructor or static factory method))
* are bound to null values - either from the JSON or as a default value. This
* is useful if you want to avoid nulls in your codebase, and particularly useful
* if you are using Java or Scala optionals for non-mandatory fields.
* Feature is disabled by default, so that no exception is thrown for missing creator
* property values, unless they are explicitly marked as `required`.
*
* @since 2.8
*/
FAIL_ON_NULL_CREATOR_PROPERTIES(false),

/**
* Feature that determines whether Jackson code should catch
* and wrap {@link Exception}s (but never {@link Error}s!)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ protected Object[] getParameters(SettableBeanProperty[] props)
}
}
}

if (_context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) {
for (int ix = 0; ix < props.length; ++ix) {
if (_creatorParameters[ix] == null) {
throw _context.mappingException("Null value for creator property '%s'; DeserializationFeature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS enabled",
props[ix].getName(), props[ix].getCreatorIndex());
}
}
}

return _creatorParameters;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.fasterxml.jackson.databind.creators;

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

/**
* Tests to ensure that deserialization fails when a bean property has a null value
* Relates to <a href="https://github.com/FasterXML/jackson-databind/issues/988">issue #988</a>
*/
public class FailOnNullCreatorTest extends BaseMapTest
{
static class Person {
String name;
Integer age;

@JsonCreator
public Person(@JsonProperty(value="name") String name,
@JsonProperty(value="age") int age)
{
this.name = name;
this.age = age;
}
}

private final ObjectReader POINT_READER = objectMapper().readerFor(Person.class);

public void testRequiredNonNullParam() throws Exception
{
Person p;
// First: fine if feature is not enabled
p = POINT_READER.readValue(aposToQuotes("{}"));
assertEquals(null, p.name);
assertEquals(Integer.valueOf(0), p.age);

// Second: fine if feature is enabled but default value is not null
ObjectReader r = POINT_READER.with(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES);
p = POINT_READER.readValue(aposToQuotes("{'name':'John', 'age': null}"));
assertEquals("John", p.name);
assertEquals(Integer.valueOf(0), p.age);

// Third: throws exception if property is missing
try {
r.readValue(aposToQuotes("{}"));
fail("Should not pass third test");
} catch (JsonMappingException e) {
verifyException(e, "Null value for creator property 'name'");
}

// Fourth: throws exception if property is set to null explicitly
try {
r.readValue(aposToQuotes("{'age': 5, 'name': null}"));
fail("Should not pass fourth test");
} catch (JsonMappingException e) {
verifyException(e, "Null value for creator property 'name'");
}
}


}