Skip to content

Commit 49c744d

Browse files
committed
minor changes to go with #2922 (improved exception messages for failed coercion from empty String)
1 parent 98c2320 commit 49c744d

File tree

4 files changed

+59
-23
lines changed

4 files changed

+59
-23
lines changed

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

+36-17
Original file line numberDiff line numberDiff line change
@@ -248,23 +248,7 @@ public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt)
248248
// there is also possibility of "auto-wrapping" of single-element arrays.
249249
// Hence we only accept empty String here.
250250
if (p.hasToken(JsonToken.VALUE_STRING)) {
251-
// 05-Nov-2020, ckozak: As per [jackson-databind#2922] string values may be handled
252-
// using handleNonArray, however empty strings may result in a null or empty collection
253-
// depending on configuration.
254-
final CoercionAction act = ctxt.findCoercionAction(logicalType(), handledType(),
255-
CoercionInputShape.EmptyString);
256-
// 05-Nov-2020, ckozak: Unclear if TryConvert should return the default
257-
// conversion (null) or fall through to handleNonArray.
258-
if (act != null
259-
// handleNonArray may successfully deserialize the result (if
260-
// ACCEPT_SINGLE_VALUE_AS_ARRAY is enabled, for example) otherwise it
261-
// is capable of failing just as well as _deserializeFromEmptyString.
262-
&& act != CoercionAction.Fail
263-
// getValueAsString call is ordered last to avoid unnecessarily building a string value.
264-
&& p.getValueAsString().isEmpty()) {
265-
return (Collection<Object>) _deserializeFromEmptyString(
266-
p, ctxt, act, handledType(), "empty String (\"\")");
267-
}
251+
return _deserializeFromString(p, ctxt, p.getText());
268252
}
269253
return handleNonArray(p, ctxt, createDefaultInstance(ctxt));
270254
}
@@ -300,6 +284,41 @@ public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
300284
return typeDeserializer.deserializeTypedFromArray(p, ctxt);
301285
}
302286

287+
/**
288+
* Logic extracted to deal with incoming String value.
289+
*
290+
* @since 2.12
291+
*/
292+
@SuppressWarnings("unchecked")
293+
protected Collection<Object> _deserializeFromString(JsonParser p, DeserializationContext ctxt,
294+
String value)
295+
throws IOException
296+
{
297+
final Class<?> rawTargetType = handledType();
298+
299+
// 05-Nov-2020, ckozak: As per [jackson-databind#2922] string values may be handled
300+
// using handleNonArray, however empty strings may result in a null or empty collection
301+
// depending on configuration.
302+
303+
// Start by verifying if we got empty/blank string since accessing
304+
// CoercionAction may be costlier than String value we'll almost certainly
305+
// need anyway
306+
if (value.isEmpty()) { // ... in future may want to allow blank, too?
307+
CoercionAction act = ctxt.findCoercionAction(logicalType(), rawTargetType,
308+
CoercionInputShape.EmptyString);
309+
act = _checkCoercionFail(ctxt, act, rawTargetType, value,
310+
"empty String (\"\")");
311+
if (act != null) {
312+
// handleNonArray may successfully deserialize the result (if
313+
// ACCEPT_SINGLE_VALUE_AS_ARRAY is enabled, for example) otherwise it
314+
// is capable of failing just as well as _deserializeFromEmptyString.
315+
return (Collection<Object>) _deserializeFromEmptyString(
316+
p, ctxt, act, rawTargetType, "empty String (\"\")");
317+
}
318+
}
319+
return handleNonArray(p, ctxt, createDefaultInstance(ctxt));
320+
}
321+
303322
/**
304323
* @since 2.12
305324
*/

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

+11-2
Original file line numberDiff line numberDiff line change
@@ -316,23 +316,32 @@ protected T _deserializeFromString(JsonParser p, DeserializationContext ctxt)
316316
protected Object _deserializeFromEmptyString(JsonParser p, DeserializationContext ctxt,
317317
CoercionAction act, Class<?> rawTargetType, String desc) throws IOException
318318
{
319+
319320
switch (act) {
320321
case AsEmpty:
321322
return getEmptyValue(ctxt);
323+
case Fail:
324+
// This will throw an exception
325+
_checkCoercionFail(ctxt, act, rawTargetType, "", "empty String (\"\")");
326+
// ... so will never fall through
322327
case TryConvert:
323328
// hmmmh... empty or null, typically? Assume "as null" for now
324329
case AsNull:
330+
default:
325331
return null;
326-
case Fail:
327-
break;
328332
}
333+
334+
// 06-Nov-2020, tatu: This was behavior pre-2.12, giving less useful
335+
// exception
336+
/*
329337
final ValueInstantiator inst = getValueInstantiator();
330338
331339
// 03-Jun-2020, tatu: Should ideally call `handleUnexpectedToken()` instead, but
332340
// since this call was already made, use it.
333341
return ctxt.handleMissingInstantiator(rawTargetType, inst, p,
334342
"Cannot deserialize value of type %s from %s (no String-argument constructor/factory method; coercion not enabled)",
335343
ClassUtil.getTypeDescription(getValueType(ctxt)), desc);
344+
*/
336345
}
337346

338347
/**

src/test/java/com/fasterxml/jackson/databind/convert/CoerceContainersTest.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,11 @@ private void _verifyNoCoercion(JavaType targetType) throws Exception {
160160
VANILLA_MAPPER.readerFor(targetType).readValue(JSON_EMPTY);
161161
fail("Should not pass");
162162
} catch (Exception e) {
163-
verifyException(e, "Cannot deserialize value of type");
164-
verifyException(e, "from empty String", "from String value (token `JsonToken.VALUE_STRING`)");
163+
// 06-Nov-2020, tatu: tests for failure get rather fragile unfortunately,
164+
// but this seems to be what we should be getting
165+
166+
verifyException(e, "Cannot coerce empty String");
167+
// verifyException(e, "Cannot deserialize value of type");
165168
}
166169
}
167170

src/test/java/com/fasterxml/jackson/databind/convert/CoercePojosTest.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,13 @@ private void _verifyFromEmptyFail(ObjectMapper m, String json) throws Exception
181181

182182
private void _verifyFailMessage(JsonProcessingException e)
183183
{
184-
verifyException(e, "Cannot deserialize value of type ");
185-
verifyException(e, " from empty String ", " from blank String ");
184+
// 06-Nov-2020, tatu: tests for failure get rather fragile unfortunately,
185+
// but this seems to be what we should be getting
186+
187+
verifyException(e, "Cannot coerce empty String");
188+
// verifyException(e, "Cannot deserialize value of type ");
189+
// verifyException(e, " from empty String ", " from blank String ");
190+
186191
assertValidLocation(e.getLocation());
187192
}
188193
}

0 commit comments

Comments
 (0)