1+ package com .fasterxml .jackson .databind .deser .filter ;
2+
3+ import com .fasterxml .jackson .annotation .JsonCreator ;
4+ import com .fasterxml .jackson .annotation .JsonProperty ;
5+ import com .fasterxml .jackson .annotation .JsonSetter ;
6+ import com .fasterxml .jackson .annotation .Nulls ;
7+ import com .fasterxml .jackson .databind .ObjectMapper ;
8+ import com .fasterxml .jackson .databind .json .JsonMapper ;
9+ import org .junit .jupiter .api .Test ;
10+
11+ import java .util .ArrayList ;
12+ import java .util .List ;
13+ import java .util .Objects ;
14+
15+ import static com .fasterxml .jackson .databind .BaseTest .a2q ;
16+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
17+
18+ // [databind#4441] @JsonSetter(nulls = Nulls.SKIP) doesn't work in some situations
19+ public class SkipNulls4441Test {
20+
21+ static class Middle {
22+ @ JsonSetter (nulls = Nulls .SKIP )
23+ private final List <Inner > listInner = new ArrayList <>();
24+ private final String field1 ;
25+
26+ @ JsonCreator
27+ public Middle (@ JsonProperty ("field1" ) String field1 ) {
28+ this .field1 = field1 ;
29+ }
30+
31+ public List <Inner > getListInner () {
32+ return listInner ;
33+ }
34+
35+ public String getField1 () {
36+ return field1 ;
37+ }
38+ }
39+
40+ static class Inner {
41+ private final String field1 ;
42+
43+ @ JsonCreator
44+ public Inner (@ JsonProperty ("field1" ) String field1 ) {
45+ this .field1 = field1 ;
46+ }
47+
48+ public String getField1 () {
49+ return field1 ;
50+ }
51+ }
52+
53+ static class MiddleSetter {
54+ private List <InnerSetter > listInner = new ArrayList <>();
55+ private final String field1 ;
56+
57+ @ JsonCreator
58+ public MiddleSetter (@ JsonProperty ("field1" ) String field1 ) {
59+ this .field1 = field1 ;
60+ }
61+
62+ @ JsonSetter (nulls = Nulls .SKIP )
63+ public void setListInner (List <InnerSetter > listInner ) {
64+ // null passed here
65+ Objects .requireNonNull (listInner );
66+ this .listInner = listInner ;
67+ }
68+
69+ public List <InnerSetter > getListInner () {
70+ return listInner ;
71+ }
72+
73+ public String getField1 () {
74+ return field1 ;
75+ }
76+ }
77+
78+ static class InnerSetter {
79+ private final String field1 ;
80+
81+ @ JsonCreator
82+ public InnerSetter (@ JsonProperty ("field1" ) String field1 ) {
83+ this .field1 = field1 ;
84+ }
85+
86+ public String getField1 () {
87+ return field1 ;
88+ }
89+ }
90+
91+ private final ObjectMapper objectMapper = JsonMapper .builder ().build ();
92+
93+ private final String NULL_ENDING_JSON = a2q ("{" +
94+ " 'field1': 'data', " +
95+ " 'listInner': null " +
96+ "}" );
97+
98+ private final String NULL_BEGINNING_JSON = a2q ("{" +
99+ " 'listInner': null, " +
100+ " 'field1': 'data' " +
101+ "}" );
102+
103+ @ Test
104+ public void testFields () throws Exception {
105+ // Passes
106+ // For some reason, if most-inner "list1" field is null in the end, it works
107+ _testFieldNullSkip (NULL_ENDING_JSON );
108+ // Fails
109+ // But if it's null in the beginning, it doesn't work
110+ _testFieldNullSkip (NULL_BEGINNING_JSON );
111+ }
112+
113+ @ Test
114+ public void testMethods () throws Exception {
115+ // Passes
116+ // For some reason, if most-inner "list1" field is null in the end, it works
117+ _testMethodNullSkip (NULL_ENDING_JSON );
118+ // Fails
119+ // But if it's null in the beginning, it doesn't work
120+ _testMethodNullSkip (NULL_BEGINNING_JSON );
121+ }
122+
123+ private void _testMethodNullSkip (String s ) throws Exception {
124+ MiddleSetter middle = objectMapper .readValue (s , MiddleSetter .class );
125+
126+ testMiddleSetter (middle );
127+ }
128+
129+ private void _testFieldNullSkip (String s ) throws Exception {
130+ Middle middle = objectMapper .readValue (s , Middle .class );
131+
132+ testMiddle (middle );
133+ }
134+
135+ private void testMiddle (Middle middle ) {
136+ validateNotNull (middle );
137+ validateNotNull (middle .getField1 ());
138+ validateNotNull (middle .getListInner ());
139+ }
140+
141+ private void testMiddleSetter (MiddleSetter middle ) {
142+ validateNotNull (middle );
143+ validateNotNull (middle .getField1 ());
144+ validateNotNull (middle .getListInner ());
145+ }
146+
147+ private static void validateNotNull (Object o ) {
148+ assertNotNull (o );
149+ }
150+ }
0 commit comments