FasterXML / FasterXML/jackson-databind

Constructor binding: absent vs null

Open
#6,063 10 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
3.7k
Forks
1.5k
Avg merge
3d 6h
Merged PRs (30d)
28

Description

I have a strict json mapper, forbidding all type coercions:

```
JsonMapper.builder()
.withCoercionConfigDefaults(coercionConfig -> {
coercionConfig.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
.setCoercion(CoercionInputShape.String, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Object, CoercionAction.Fail);
})
.changeDefaultNullHandling(_ -> JsonSetter.Value.construct(Nulls.FAIL, Nulls.FAIL))
.build()
```

And I would like to use my DTOs with constructors instead of setters:

```
public class TestClass {
private String propertyA;
private String propertyB;

// This.
public TestClass(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
}

// Over this.
// public void setPropertyA(String propertyA) {
// this.propertyA = propertyA;
// }

public String getPropertyA() {
return propertyA;
}

// public void setPropertyB(String propertyB) {
// this.propertyB = propertyB;
// }

public String getPropertyB() {
return propertyB;
}
}
```

If I do this:

```
jsonMapper.readValue("{ \"propertyA\": \"value\" }", TestClass.class);
```

I will obtain the following exception:

```
Invalid `null` value encountered for property "propertyB"
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); byte offset: #UNKNOWN] (through reference chain: TestClass["propertyB"])
tools.jackson.databind.exc.InvalidNullException: Invalid `null` value encountered for property "propertyB"
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); byte offset: #UNKNOWN] (through reference chain: TestClass["propertyB"])
```

I would expect this error to be thrown if I provided `\"propertyB\": null` but not in this situation.

I understand that this is caused by my null configuration, however, we need to keep it.

Is what I am trying to achieve possible out of the box? That is, not providing propertyB is acceptable while providing it with value null is not (absent is ok, explicit null is forbidden).

Originally reported in https://github.com/FasterXML/jackson-databind/issues/3847/ in a slightly different manner.

Versions used:

- com.fasterxml.jackson.core:jackson-annotations:2.21
- tools.jackson.core:jackson-core:3.1.4
- tools.jackson.core:jackson-databind:3.1.4

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the provided TestClass reproducer and the JsonMapper.readValue call, then trace constructor binding together with the configured Nulls.FAIL handling. Done means an absent property is accepted while an explicitly supplied null still raises the invalid-null error, without changing the strict coercion and null configuration.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.