Skip to content

Commit f760b6d

Browse files
committed
Fix #2567 (wrong target type for failed null check)
1 parent a9017ec commit f760b6d

File tree

6 files changed

+40
-26
lines changed

6 files changed

+40
-26
lines changed

release-notes/CREDITS-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,8 @@ João Guerra (joca-bt@github)
984984
* Reported #2473: Array index missing in path of `JsonMappingException` for `Collection<String>`,
985985
with custom deserializer
986986
(2.10.1)
987+
* Reported #2567: Incorrect target type for arrays when providing nulls and nulls are disabled
988+
(2.10.2)
987989
988990
Ryan Bohn (bohnman@github)
989991
* Reported #2475: `StringCollectionSerializer` calls `JsonGenerator.setCurrentValue(value)`,

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Project: jackson-databind
1414
(reported by Fabian L)
1515
#2560: Check `WRAP_EXCEPTIONS` in `CollectionDeserializer.handleNonArray()`
1616
(reported by Stefan W)
17+
#2567: Incorrect target type for arrays when providing nulls and nulls are disabled
18+
(reported by João G)
1719

1820
2.10.1 (09-Nov-2019)
1921

src/main/java/com/fasterxml/jackson/databind/deser/impl/NullsFailProvider.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ protected NullsFailProvider(PropertyName name, JavaType type) {
2323
}
2424

2525
public static NullsFailProvider constructForProperty(BeanProperty prop) {
26-
return new NullsFailProvider(prop.getFullName(), prop.getType());
26+
return constructForProperty(prop, prop.getType());
27+
}
28+
29+
// @since 2.10.2
30+
public static NullsFailProvider constructForProperty(BeanProperty prop, JavaType type) {
31+
return new NullsFailProvider(prop.getFullName(), type);
2732
}
2833

2934
public static NullsFailProvider constructForRootValue(JavaType t) {

src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java

+5-25
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,11 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
110110
nuller = NullsConstantProvider.skipper();
111111
} else if (nullStyle == Nulls.FAIL) {
112112
if (property == null) {
113-
nuller = NullsFailProvider.constructForRootValue(ctxt.constructType(_valueClass));
113+
// 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type
114+
nuller = NullsFailProvider.constructForRootValue(ctxt.constructType(_valueClass.getComponentType()));
114115
} else {
115-
nuller = NullsFailProvider.constructForProperty(property);
116+
// 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type
117+
nuller = NullsFailProvider.constructForProperty(property, property.getType().getContentType());
116118
}
117119
}
118120
if ((unwrapSingle == _unwrapSingle) && (nuller == _nuller)) {
@@ -198,29 +200,7 @@ public T deserialize(JsonParser p, DeserializationContext ctxt, T existing) thro
198200
/* Helper methods for sub-classes
199201
/********************************************************
200202
*/
201-
202-
/*
203-
* Convenience method that constructs a concatenation of two arrays,
204-
* with the type they have.
205-
*
206-
* @since 2.9
207-
@SuppressWarnings("unchecked")
208-
public static <T> T concatArrays(T array1, T array2)
209-
{
210-
int len1 = Array.getLength(array1);
211-
if (len1 == 0) {
212-
return array2;
213-
}
214-
int len2 = Array.getLength(array2);
215-
if (len2 == 0) {
216-
return array1;
217-
}
218-
Object result = Arrays.copyOf((Object[]) array1, len1 + len2);
219-
System.arraycopy(array2, 0, result, len1, len2);
220-
return (T) result;
221-
}
222-
*/
223-
203+
224204
@SuppressWarnings("unchecked")
225205
protected T handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException
226206
{

src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java

+14
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,20 @@ protected NullValueProvider findContentNullProvider(DeserializationContext ctxt,
10981098
if (nulls == Nulls.SKIP) {
10991099
return NullsConstantProvider.skipper();
11001100
}
1101+
// 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type (element,
1102+
// not container), so inlined here before calling _findNullProvider
1103+
if (nulls == Nulls.FAIL) {
1104+
if (prop == null) {
1105+
JavaType type = ctxt.constructType(valueDeser.handledType());
1106+
// should always be container? But let's double-check just in case:
1107+
if (type.isContainerType()) {
1108+
type = type.getContentType();
1109+
}
1110+
return NullsFailProvider.constructForRootValue(type);
1111+
}
1112+
return NullsFailProvider.constructForProperty(prop, prop.getType().getContentType());
1113+
}
1114+
11011115
NullValueProvider prov = _findNullProvider(ctxt, prop, nulls, valueDeser);
11021116
if (prov != null) {
11031117
return prov;

src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForContentTest.java

+11
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public void testFailOnNullFromDefaults() throws Exception
6262
fail("Should not pass");
6363
} catch (InvalidNullException e) {
6464
verifyException(e, "property \"values\"");
65+
assertEquals(String.class, e.getTargetType());
6566
}
6667

6768
// or configured for type:
@@ -73,6 +74,7 @@ public void testFailOnNullFromDefaults() throws Exception
7374
fail("Should not pass");
7475
} catch (InvalidNullException e) {
7576
verifyException(e, "property \"values\"");
77+
assertEquals(String.class, e.getTargetType());
7678
}
7779
}
7880

@@ -96,6 +98,7 @@ public void testFailOnNullWithCollections() throws Exception
9698
fail("Should not pass");
9799
} catch (InvalidNullException e) {
98100
verifyException(e, "property \"noNulls\"");
101+
assertEquals(Integer.class, e.getTargetType());
99102
}
100103

101104
// List<String>
@@ -104,6 +107,7 @@ public void testFailOnNullWithCollections() throws Exception
104107
fail("Should not pass");
105108
} catch (InvalidNullException e) {
106109
verifyException(e, "property \"noNulls\"");
110+
assertEquals(String.class, e.getTargetType());
107111
}
108112
}
109113

@@ -116,6 +120,7 @@ public void testFailOnNullWithArrays() throws Exception
116120
fail("Should not pass");
117121
} catch (InvalidNullException e) {
118122
verifyException(e, "property \"noNulls\"");
123+
assertEquals(Object.class, e.getTargetType());
119124
}
120125

121126
// String[]
@@ -124,6 +129,7 @@ public void testFailOnNullWithArrays() throws Exception
124129
fail("Should not pass");
125130
} catch (InvalidNullException e) {
126131
verifyException(e, "property \"noNulls\"");
132+
assertEquals(String.class, e.getTargetType());
127133
}
128134
}
129135

@@ -137,20 +143,23 @@ public void testFailOnNullWithPrimitiveArrays() throws Exception
137143
fail("Should not pass");
138144
} catch (InvalidNullException e) {
139145
verifyException(e, "property \"noNulls\"");
146+
assertEquals(Boolean.TYPE, e.getTargetType());
140147
}
141148
// int[]
142149
try {
143150
MAPPER.readValue(JSON, new TypeReference<NullContentFail<int[]>>() { });
144151
fail("Should not pass");
145152
} catch (InvalidNullException e) {
146153
verifyException(e, "property \"noNulls\"");
154+
assertEquals(Integer.TYPE, e.getTargetType());
147155
}
148156
// double[]
149157
try {
150158
MAPPER.readValue(JSON, new TypeReference<NullContentFail<double[]>>() { });
151159
fail("Should not pass");
152160
} catch (InvalidNullException e) {
153161
verifyException(e, "property \"noNulls\"");
162+
assertEquals(Double.TYPE, e.getTargetType());
154163
}
155164
}
156165

@@ -163,6 +172,7 @@ public void testFailOnNullWithMaps() throws Exception
163172
fail("Should not pass");
164173
} catch (InvalidNullException e) {
165174
verifyException(e, "property \"noNulls\"");
175+
assertEquals(String.class, e.getTargetType());
166176
}
167177

168178
// Then: EnumMap<Enum,String>
@@ -172,6 +182,7 @@ public void testFailOnNullWithMaps() throws Exception
172182
fail("Should not pass");
173183
} catch (InvalidNullException e) {
174184
verifyException(e, "property \"noNulls\"");
185+
assertEquals(String.class, e.getTargetType());
175186
}
176187
}
177188

0 commit comments

Comments
 (0)