Skip to content

Commit c527259

Browse files
committed
Fix #2707
1 parent 24274b2 commit c527259

File tree

9 files changed

+74
-19
lines changed

9 files changed

+74
-19
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Project: jackson-databind
88

99
#792: Deserialization Not Working Right with Generic Types and Builders
1010
(reported by Mike G; fix contributed by Ville K)
11+
#2707: Improve description included in by `DeserializationContext.handleUnexpectedToken()`
1112

1213
2.11.1 (not yet released)
1314

src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java

+53-2
Original file line numberDiff line numberDiff line change
@@ -1231,8 +1231,16 @@ public Object handleUnexpectedToken(JavaType targetType, JsonToken t,
12311231
msg = String.format("Unexpected end-of-input when binding data into %s",
12321232
ClassUtil.getTypeDescription(targetType));
12331233
} else {
1234-
msg = String.format("Cannot deserialize instance of %s out of %s token",
1235-
ClassUtil.getTypeDescription(targetType), t);
1234+
final String targetDesc = ClassUtil.getTypeDescription(targetType);
1235+
final String valueDesc = _shapeForToken(t);
1236+
if (valueDesc == null) { // no specific description
1237+
msg = String.format("Cannot deserialize instance of %s out of %s token",
1238+
targetDesc, t);
1239+
} else {
1240+
msg = String.format(
1241+
"Cannot deserialize instance of %s from %s (token `JsonToken.%s`)",
1242+
targetDesc, valueDesc, t);
1243+
}
12361244
}
12371245
}
12381246
reportInputMismatch(targetType, msg);
@@ -1919,4 +1927,47 @@ protected DateFormat getDateFormat()
19191927
_dateFormat = df = (DateFormat) df.clone();
19201928
return df;
19211929
}
1930+
1931+
// @since 2.12
1932+
/**
1933+
* Helper method for constructing description like "Object value" given
1934+
* {@link JsonToken} encountered.
1935+
*/
1936+
protected String _shapeForToken(JsonToken t) {
1937+
if (t != null) {
1938+
switch (t) {
1939+
// Likely Object values
1940+
case START_OBJECT:
1941+
case END_OBJECT:
1942+
case FIELD_NAME:
1943+
return "Object value";
1944+
1945+
// Likely Array values
1946+
case START_ARRAY:
1947+
case END_ARRAY:
1948+
return "Array value";
1949+
1950+
case VALUE_FALSE:
1951+
case VALUE_TRUE:
1952+
return "Boolean value";
1953+
1954+
case VALUE_EMBEDDED_OBJECT:
1955+
return "Embedded Object";
1956+
1957+
case VALUE_NUMBER_FLOAT:
1958+
case VALUE_NUMBER_INT:
1959+
return "Number value";
1960+
case VALUE_STRING:
1961+
return "String value";
1962+
1963+
case VALUE_NULL:
1964+
return "Null value";
1965+
1966+
case NOT_AVAILABLE:
1967+
default:
1968+
return "[Unavailable value]";
1969+
}
1970+
}
1971+
return "<end of input>";
1972+
}
19221973
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ public void testUnexpectedTokenHandling() throws Exception
362362
mapper.readValue("true", Integer.class);
363363
fail("Should not pass");
364364
} catch (MismatchedInputException e) {
365-
verifyException(e, "out of VALUE_TRUE token");
365+
verifyException(e, "from Boolean value (token `JsonToken.VALUE_TRUE`)");
366366
}
367367
}
368368
}

src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ public void testCalendarArrayUnwrap() throws Exception
702702
fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
703703
} catch (MismatchedInputException exp) {
704704
verifyException(exp, "Cannot deserialize");
705-
verifyException(exp, "out of START_ARRAY");
705+
verifyException(exp, "from Array value (token `JsonToken.START_ARRAY`)");
706706
}
707707

708708
reader = reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);

src/test/java/com/fasterxml/jackson/databind/exc/ExceptionDeserializationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public void testSingleValueArrayDeserializationException() throws Exception {
157157
mapper.readValue(value, IOException.class);
158158
fail("Exception not thrown when attempting to deserialize an IOException wrapped in a single value array with UNWRAP_SINGLE_VALUE_ARRAYS disabled");
159159
} catch (JsonMappingException exp2) {
160-
verifyException(exp2, "out of START_ARRAY");
160+
verifyException(exp2, "from Array value (token `JsonToken.START_ARRAY`)");
161161
}
162162
}
163163

src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ public void testSimpleMismatch() throws Exception
359359
mapper.readValue(" 123 ", ArrayNode.class);
360360
fail("Should not pass");
361361
} catch (MismatchedInputException e) {
362-
verifyException(e, "out of VALUE_NUMBER_INT token");
362+
verifyException(e, "from Number value (token `JsonToken.VALUE_NUMBER_INT`)");
363363
}
364364
}
365365
}

src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ public void testSimpleMismatch() throws Exception
463463
mapper.readValue("[ 1, 2, 3 ]", ObjectNode.class);
464464
fail("Should not pass");
465465
} catch (MismatchedInputException e) {
466-
verifyException(e, "out of START_ARRAY token");
466+
verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
467467
}
468468
}
469469
}

src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public void testPOJOFromEmptyArray() throws Exception
5454
.readValue(EMPTY_ARRAY);
5555
fail("Should not accept Empty Array for POJO by default");
5656
} catch (JsonMappingException e) {
57-
verifyException(e, "START_ARRAY token");
57+
verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
5858
assertValidLocation(e.getLocation());
5959
}
6060

@@ -78,7 +78,7 @@ public void testMapFromEmptyArray() throws Exception
7878
.readValue(EMPTY_ARRAY);
7979
fail("Should not accept Empty Array for Map by default");
8080
} catch (JsonMappingException e) {
81-
verifyException(e, "START_ARRAY token");
81+
verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
8282
}
8383
// should be ok to enable dynamically:
8484
Map<?,?> result = READER_WITH_ARRAYS.forType(Map.class)

src/test/java/com/fasterxml/jackson/databind/struct/UnwrapSingleArrayScalarsTest.java

+13-10
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ public void testSingleString() throws Exception
245245
String result = MAPPER.readValue("\""+value+"\"", String.class);
246246
assertEquals(value, result);
247247
}
248-
248+
249249
public void testSingleStringWrapped() throws Exception
250250
{
251251
final ObjectMapper mapper = new ObjectMapper();
@@ -256,8 +256,7 @@ public void testSingleStringWrapped() throws Exception
256256
mapper.readValue("[\""+value+"\"]", String.class);
257257
fail("Exception not thrown when attempting to unwrap a single value 'String' array into a simple String");
258258
} catch (MismatchedInputException exp) {
259-
verifyException(exp, "Cannot deserialize");
260-
verifyException(exp, "out of START_ARRAY");
259+
_verifyNoDeserFromArray(exp);
261260
}
262261

263262
mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
@@ -284,8 +283,7 @@ public void testBigDecimal() throws Exception
284283
mapper.readValue("[" + value.toString() + "]", BigDecimal.class);
285284
fail("Exception was not thrown when attempting to read a single value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
286285
} catch (MismatchedInputException exp) {
287-
verifyException(exp, "Cannot deserialize");
288-
verifyException(exp, "out of START_ARRAY");
286+
_verifyNoDeserFromArray(exp);
289287
}
290288

291289
mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
@@ -313,8 +311,7 @@ public void testBigInteger() throws Exception
313311
mapper.readValue("[" + value.toString() + "]", BigInteger.class);
314312
fail("Exception was not thrown when attempting to read a single value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
315313
} catch (MismatchedInputException exp) {
316-
verifyException(exp, "Cannot deserialize");
317-
verifyException(exp, "out of START_ARRAY");
314+
_verifyNoDeserFromArray(exp);
318315
}
319316

320317
mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
@@ -343,7 +340,7 @@ public void testClassAsArray() throws Exception
343340
.readValue("[" + quote(String.class.getName()) + "]");
344341
fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was disabled and attempted to read a Class array containing one element");
345342
} catch (MismatchedInputException e) {
346-
verifyException(e, "out of START_ARRAY token");
343+
_verifyNoDeserFromArray(e);
347344
}
348345

349346
_verifyMultiValueArrayFail("[" + quote(Object.class.getName()) + "," + quote(Object.class.getName()) +"]",
@@ -363,7 +360,7 @@ public void testURIAsArray() throws Exception
363360
.readValue("[\""+value.toString()+"\"]");
364361
fail("Did not throw exception for single value array when UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
365362
} catch (MismatchedInputException e) {
366-
verifyException(e, "out of START_ARRAY token");
363+
_verifyNoDeserFromArray(e);
367364
}
368365

369366
_verifyMultiValueArrayFail("[\""+value.toString()+"\",\""+value.toString()+"\"]", URI.class);
@@ -379,7 +376,7 @@ public void testUUIDAsArray() throws Exception
379376
.readValue("[" + quote(uuidStr) + "]");
380377
fail("Exception was not thrown when UNWRAP_SINGLE_VALUE_ARRAYS is disabled and attempted to read a single value array as a single element");
381378
} catch (MismatchedInputException e) {
382-
verifyException(e, "out of START_ARRAY token");
379+
_verifyNoDeserFromArray(e);
383380
}
384381
assertEquals(uuid,
385382
reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
@@ -393,6 +390,12 @@ public void testUUIDAsArray() throws Exception
393390
/**********************************************************
394391
*/
395392

393+
private void _verifyNoDeserFromArray(Exception e) {
394+
verifyException(e, "Cannot deserialize");
395+
verifyException(e, "from Array value");
396+
verifyException(e, "JsonToken.START_ARRAY");
397+
}
398+
396399
private void _verifyMultiValueArrayFail(String input, Class<?> type) throws IOException {
397400
try {
398401
UNWRAPPING_READER.forType(type).readValue(input);

0 commit comments

Comments
 (0)