Skip to content

Commit 20a67f7

Browse files
committed
Fix #1000; now UUID and Enum deserializers should throw InvalidFormatException as expected
1 parent dc87afa commit 20a67f7

File tree

5 files changed

+43
-18
lines changed

5 files changed

+43
-18
lines changed

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Project: jackson-databind
4444
(reported by Shumpei A)
4545
#997: Add `MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS`
4646
#998: Allow use of `NON_DEFAULT` for POJOs without default constructor
47+
#1000: Add new mapping exception type for enums and UUIDs
48+
(suggesed by natnan@github)
4749
#1011: Change ObjectWriter::withAttributes() to take a Map with some kind of wildcard types
4850
(suggested by David B)
4951
- Make `JsonValueFormat` (self-)serializable, deserializable, to/from valid external

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

+23-6
Original file line numberDiff line numberDiff line change
@@ -905,8 +905,8 @@ public JsonMappingException instantiationException(Class<?> instClass, String ms
905905
*/
906906
public JsonMappingException weirdStringException(String value, Class<?> instClass, String msg) {
907907
return InvalidFormatException.from(_parser,
908-
String.format("Can not construct instance of %s from String value '%s': %s",
909-
instClass.getName(), _valueDesc(), msg),
908+
String.format("Can not construct instance of %s from String value (%s): %s",
909+
instClass.getName(), _quotedString(value), msg),
910910
value, instClass);
911911
}
912912

@@ -917,8 +917,8 @@ public JsonMappingException weirdStringException(String value, Class<?> instClas
917917
public JsonMappingException weirdNumberException(Number value, Class<?> instClass, String msg) {
918918
return InvalidFormatException.from(_parser,
919919
String.format("Can not construct instance of %s from number value (%s): %s",
920-
instClass.getName(), _valueDesc(), msg),
921-
null, instClass);
920+
instClass.getName(), String.valueOf(value), msg),
921+
value, instClass);
922922
}
923923

924924
/**
@@ -928,8 +928,8 @@ public JsonMappingException weirdNumberException(Number value, Class<?> instClas
928928
*/
929929
public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg) {
930930
return InvalidFormatException.from(_parser,
931-
String.format("Can not construct Map key of type %s from String \"%s\": ",
932-
keyClass.getName(), _desc(keyValue), msg),
931+
String.format("Can not construct Map key of type %s from String (%s): %s",
932+
keyClass.getName(), _quotedString(keyValue), msg),
933933
keyValue, keyClass);
934934
}
935935

@@ -1019,10 +1019,27 @@ protected String _valueDesc() {
10191019
}
10201020

10211021
protected String _desc(String desc) {
1022+
if (desc == null) {
1023+
return "[N/A]";
1024+
}
10221025
// !!! should we quote it? (in case there are control chars, linefeeds)
10231026
if (desc.length() > MAX_ERROR_STR_LEN) {
10241027
desc = desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN);
10251028
}
10261029
return desc;
10271030
}
1031+
1032+
// @since 2.7
1033+
protected String _quotedString(String desc) {
1034+
if (desc == null) {
1035+
return "[N/A]";
1036+
}
1037+
// !!! should we quote it? (in case there are control chars, linefeeds)
1038+
if (desc.length() > MAX_ERROR_STR_LEN) {
1039+
return String.format("\"%s]...[%s\"",
1040+
desc.substring(0, MAX_ERROR_STR_LEN),
1041+
desc.substring(desc.length() - MAX_ERROR_STR_LEN));
1042+
}
1043+
return "\"" + desc + "\"";
1044+
}
10281045
}

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

+16-10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.fasterxml.jackson.databind.*;
88
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
99
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
10+
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
1011
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
1112
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
1213
import com.fasterxml.jackson.databind.util.ClassUtil;
@@ -88,15 +89,16 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
8889
}
8990
// But let's consider int acceptable as well (if within ordinal range)
9091
if (curr == JsonToken.VALUE_NUMBER_INT) {
91-
// ... unless told not to do that. :-) (as per [JACKSON-412])
92-
_checkFailOnNumber(ctxt);
93-
92+
// ... unless told not to do that
9493
int index = p.getIntValue();
94+
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
95+
_failOnNumber(ctxt, p, index);
96+
}
9597
if (index >= 0 && index <= _enumsByIndex.length) {
9698
return _enumsByIndex[index];
9799
}
98100
if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
99-
throw ctxt.weirdNumberException(Integer.valueOf(index), _enumClass(),
101+
throw ctxt.weirdNumberException(index, _enumClass(),
100102
"index value outside legal index range [0.."+(_enumsByIndex.length-1)+"]");
101103
}
102104
return null;
@@ -113,12 +115,14 @@ private final Object _deserializeAltString(JsonParser p, DeserializationContext
113115
return null;
114116
}
115117
} else {
116-
// [#149]: Allow use of 'String' indexes as well
118+
// [databind#149]: Allow use of 'String' indexes as well
117119
char c = name.charAt(0);
118120
if (c >= '0' && c <= '9') {
119121
try {
120122
int ix = Integer.parseInt(name);
121-
_checkFailOnNumber(ctxt);
123+
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
124+
_failOnNumber(ctxt, p, ix);
125+
}
122126
if (ix >= 0 && ix <= _enumsByIndex.length) {
123127
return _enumsByIndex[ix];
124128
}
@@ -152,11 +156,13 @@ protected Object _deserializeOther(JsonParser p, DeserializationContext ctxt) th
152156
throw ctxt.mappingException(_enumClass());
153157
}
154158

155-
protected void _checkFailOnNumber(DeserializationContext ctxt) throws IOException
159+
protected void _failOnNumber(DeserializationContext ctxt, JsonParser p, int index)
160+
throws IOException
156161
{
157-
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)) {
158-
throw ctxt.mappingException("Not allowed to deserialize Enum value out of JSON number (disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow)");
159-
}
162+
throw InvalidFormatException.from(p,
163+
String.format("Not allowed to deserialize Enum value out of JSON number (%d): disable DeserializationConfig.DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS to allow",
164+
index),
165+
index, _enumClass());
160166
}
161167

162168
protected Class<?> _enumClass() {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ public Object _parse(String key, DeserializationContext ctxt) throws JsonMapping
339339
}
340340
}
341341
Enum<?> e = _resolver.findEnum(key);
342-
if (e == null && !ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
342+
if ((e == null) && !ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
343343
throw ctxt.weirdKeyException(_keyClass, key, "not one of values for Enum class");
344344
}
345345
return e;

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public void testErrorReporting() throws Exception
124124
try {
125125
MAPPER.readValue("{\"boolProp\":\"foobar\"}", BooleanBean.class);
126126
} catch (JsonMappingException e) {
127-
verifyException(e, "from String value 'foobar'");
127+
verifyException(e, "from String value (\"foobar\")");
128128
}
129129
}
130130

0 commit comments

Comments
 (0)