Skip to content

Commit

Permalink
Fix #4441 (#4469)
Browse files Browse the repository at this point in the history
  • Loading branch information
JooHyukKim authored Apr 7, 2024
1 parent 7c9e7c1 commit 2a10288
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ public Object deserializeSetAndReturn(JsonParser p,
@Override
public void set(Object instance, Object value) throws IOException
{
if (value == null) {
if (_skipNulls) {
return;
}
}
try {
_field.set(instance, value);
} catch (Exception e) {
Expand All @@ -197,6 +202,11 @@ public void set(Object instance, Object value) throws IOException
@Override
public Object setAndReturn(Object instance, Object value) throws IOException
{
if (value == null) {
if (_skipNulls) {
return instance;
}
}
try {
_field.set(instance, value);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ public Object deserializeSetAndReturn(JsonParser p,
@Override
public final void set(Object instance, Object value) throws IOException
{
if (value == null) {
if (_skipNulls) {
return;
}
}
try {
_setter.invoke(instance, value);
} catch (Exception e) {
Expand All @@ -189,6 +194,11 @@ public final void set(Object instance, Object value) throws IOException
@Override
public Object setAndReturn(Object instance, Object value) throws IOException
{
if (value == null) {
if (_skipNulls) {
return instance;
}
}
try {
Object result = _setter.invoke(instance, value);
return (result == null) ? instance : result;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package com.fasterxml.jackson.databind.deser.filter;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.fasterxml.jackson.databind.BaseTest.a2q;
import static org.junit.jupiter.api.Assertions.assertNotNull;

// [databind#4441] @JsonSetter(nulls = Nulls.SKIP) doesn't work in some situations
public class SkipNulls4441Test {

static class Middle {
@JsonSetter(nulls = Nulls.SKIP)
private final List<Inner> listInner = new ArrayList<>();
private final String field1;

@JsonCreator
public Middle(@JsonProperty("field1") String field1) {
this.field1 = field1;
}

public List<Inner> getListInner() {
return listInner;
}

public String getField1() {
return field1;
}
}

static class Inner {
private final String field1;

@JsonCreator
public Inner(@JsonProperty("field1") String field1) {
this.field1 = field1;
}

public String getField1() {
return field1;
}
}

static class MiddleSetter {
private List<InnerSetter> listInner = new ArrayList<>();
private final String field1;

@JsonCreator
public MiddleSetter(@JsonProperty("field1") String field1) {
this.field1 = field1;
}

@JsonSetter(nulls = Nulls.SKIP)
public void setListInner(List<InnerSetter> listInner) {
// null passed here
Objects.requireNonNull(listInner);
this.listInner = listInner;
}

public List<InnerSetter> getListInner() {
return listInner;
}

public String getField1() {
return field1;
}
}

static class InnerSetter {
private final String field1;

@JsonCreator
public InnerSetter(@JsonProperty("field1") String field1) {
this.field1 = field1;
}

public String getField1() {
return field1;
}
}

private final ObjectMapper objectMapper = JsonMapper.builder().build();

private final String NULL_ENDING_JSON = a2q("{" +
" 'field1': 'data', " +
" 'listInner': null " +
"}");

private final String NULL_BEGINNING_JSON = a2q("{" +
" 'listInner': null, " +
" 'field1': 'data' " +
"}");

@Test
public void testFields() throws Exception {
// Passes
// For some reason, if most-inner "list1" field is null in the end, it works
_testFieldNullSkip(NULL_ENDING_JSON);
// Fails
// But if it's null in the beginning, it doesn't work
_testFieldNullSkip(NULL_BEGINNING_JSON);
}

@Test
public void testMethods() throws Exception {
// Passes
// For some reason, if most-inner "list1" field is null in the end, it works
_testMethodNullSkip(NULL_ENDING_JSON);
// Fails
// But if it's null in the beginning, it doesn't work
_testMethodNullSkip(NULL_BEGINNING_JSON);
}

private void _testMethodNullSkip(String s) throws Exception {
MiddleSetter middle = objectMapper.readValue(s, MiddleSetter.class);

testMiddleSetter(middle);
}

private void _testFieldNullSkip(String s) throws Exception {
Middle middle = objectMapper.readValue(s, Middle.class);

testMiddle(middle);
}

private void testMiddle(Middle middle) {
validateNotNull(middle);
validateNotNull(middle.getField1());
validateNotNull(middle.getListInner());
}

private void testMiddleSetter(MiddleSetter middle) {
validateNotNull(middle);
validateNotNull(middle.getField1());
validateNotNull(middle.getListInner());
}

private static void validateNotNull(Object o) {
assertNotNull(o);
}
}

0 comments on commit 2a10288

Please sign in to comment.