Skip to content

Commit 1ecc6b5

Browse files
committed
Fix #1017 (add InvalidTypeIdException)
1 parent 2d318f6 commit 1ecc6b5

File tree

4 files changed

+100
-12
lines changed

4 files changed

+100
-12
lines changed

release-notes/VERSION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Project: jackson-databind
1515
#990: Allow failing on `null` values for creator (add
1616
`DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES`)
1717
(contributed by mkokho@github)
18+
#1017: Add new mapping exception type ('InvalidTypeIdException') for subtype resolution errors
19+
(suggested by natnan@github)
1820
#1082: Can not use static Creator factory methods for `Enum`s, with JsonCreator.Mode.PROPERTIES
1921
(contributed by Lokesh K)
2022
#1084: Change `TypeDeserializerBase` to take `JavaType` for `defaultImpl`, NOT `Class`

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
1616
import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer;
1717
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
18+
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
1819
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
1920
import com.fasterxml.jackson.databind.introspect.Annotated;
2021
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
@@ -893,12 +894,12 @@ public JavaType handleUnknownTypeId(JavaType baseType, String id,
893894
if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
894895
return type;
895896
}
896-
throw unknownTypeException(baseType, id,
897+
throw unknownTypeIdException(baseType, id,
897898
"problem handler tried to resolve into non-subtype: "+type);
898899
}
899900
h = h.next();
900901
}
901-
throw unknownTypeException(baseType, id, extraDesc);
902+
throw unknownTypeIdException(baseType, id, extraDesc);
902903
}
903904

904905
/*
@@ -1072,7 +1073,7 @@ public JsonMappingException mappingException(String msgTemplate, Object... args)
10721073
/*
10731074
/**********************************************************
10741075
/* Methods for constructing semantic exceptions; usually not
1075-
/* to be called direclty, call `handleXxx()` instead
1076+
/* to be called directly, call `handleXxx()` instead
10761077
/**********************************************************
10771078
*/
10781079

@@ -1090,17 +1091,20 @@ public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue
10901091
}
10911092

10921093
/**
1093-
* Helper method for constructing exception to indicate that end-of-input was
1094-
* reached while still expecting more tokens to deserialize value of specified type.
1095-
*
1096-
* @deprecated Since 2.8; currently no way to catch EOF at databind level
1094+
* Helper method for constructing exception to indicate that given JSON
1095+
* Object field name was not in format to be able to deserialize specified
1096+
* key type.
10971097
*/
1098-
@Deprecated
1099-
public JsonMappingException endOfInputException(Class<?> instClass) {
1100-
return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to deserialize a "
1101-
+instClass.getName());
1098+
public JsonMappingException unknownTypeIdException(JavaType baseType, String typeId,
1099+
String extraDesc) {
1100+
String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
1101+
typeId, baseType);
1102+
if (extraDesc != null) {
1103+
msg = msg + ": "+extraDesc;
1104+
}
1105+
return InvalidTypeIdException.from(_parser, msg, baseType, typeId);
11021106
}
1103-
1107+
11041108
/*
11051109
/**********************************************************
11061110
/* Methods for constructing semantic exceptions; mostly
@@ -1200,6 +1204,18 @@ public JsonMappingException unknownTypeException(JavaType type, String id,
12001204
return JsonMappingException.from(_parser, msg);
12011205
}
12021206

1207+
/**
1208+
* Helper method for constructing exception to indicate that end-of-input was
1209+
* reached while still expecting more tokens to deserialize value of specified type.
1210+
*
1211+
* @deprecated Since 2.8; currently no way to catch EOF at databind level
1212+
*/
1213+
@Deprecated
1214+
public JsonMappingException endOfInputException(Class<?> instClass) {
1215+
return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to deserialize a "
1216+
+instClass.getName());
1217+
}
1218+
12031219
/*
12041220
/**********************************************************
12051221
/* Overridable internal methods
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.fasterxml.jackson.databind.exc;
2+
3+
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.databind.JavaType;
5+
import com.fasterxml.jackson.databind.JsonMappingException;
6+
7+
/**
8+
* Exception thrown when resolution of a type id fails.
9+
*
10+
* @since 2.8
11+
*/
12+
public class InvalidTypeIdException extends JsonMappingException
13+
{
14+
private static final long serialVersionUID = 1L; // silly Eclipse, warnings
15+
16+
/**
17+
* Basetype for which subtype was to be resolved
18+
*/
19+
protected final JavaType _baseType;
20+
21+
/**
22+
* Type id that failed to be resolved to a subtype
23+
*/
24+
protected final String _typeId;
25+
26+
/*
27+
/**********************************************************
28+
/* Life-cycle
29+
/**********************************************************
30+
*/
31+
32+
public InvalidTypeIdException(JsonParser p, String msg,
33+
JavaType baseType, String typeId)
34+
{
35+
super(p, msg);
36+
_baseType = baseType;
37+
_typeId = typeId;
38+
}
39+
40+
public static InvalidTypeIdException from(JsonParser p, String msg,
41+
JavaType baseType, String typeId) {
42+
return new InvalidTypeIdException(p, msg, baseType, typeId);
43+
}
44+
45+
/*
46+
/**********************************************************
47+
/* Accessors
48+
/**********************************************************
49+
*/
50+
51+
public JavaType getBaseType() { return _baseType; }
52+
public String getTypeId() { return _typeId; }
53+
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.fasterxml.jackson.annotation.JsonTypeInfo;
77
import com.fasterxml.jackson.databind.*;
88
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
9+
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
910

1011
/**
1112
* Tests to exercise handler methods of {@link DeserializationProblemHandler}.
@@ -66,6 +67,8 @@ static class BaseWrapper {
6667
/**********************************************************
6768
*/
6869

70+
private final ObjectMapper MAPPER = new ObjectMapper();
71+
6972
public void testWeirdKeyHandling() throws Exception
7073
{
7174
ObjectMapper mapper = new ObjectMapper()
@@ -86,4 +89,18 @@ public void testInvalidTypeId() throws Exception
8689
BaseWrapper.class);
8790
assertNotNull(w);
8891
}
92+
93+
// verify that by default we get special exception type
94+
public void testInvalidTypeIdFail() throws Exception
95+
{
96+
try {
97+
MAPPER.readValue("{\"value\":{\"type\":\"foo\",\"a\":4}}",
98+
BaseWrapper.class);
99+
fail("Should not pass");
100+
} catch (InvalidTypeIdException e) {
101+
verifyException(e, "Could not resolve type id 'foo'");
102+
assertEquals(Base.class, e.getBaseType().getRawClass());
103+
assertEquals("foo", e.getTypeId());
104+
}
105+
}
89106
}

0 commit comments

Comments
 (0)