Skip to content

Commit 33ba4ad

Browse files
committed
Added DeserializationContext.handleUnknownTypeId()
1 parent bd3c312 commit 33ba4ad

File tree

4 files changed

+101
-44
lines changed

4 files changed

+101
-44
lines changed

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

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -820,16 +820,22 @@ public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
820820
throws IOException
821821
{
822822
LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
823-
if (h != null) {
824-
while (h != null) {
825-
// Can bail out if it's handled
826-
if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
827-
return true;
828-
}
829-
h = h.next();
823+
while (h != null) {
824+
// Can bail out if it's handled
825+
if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
826+
return true;
830827
}
828+
h = h.next();
831829
}
832-
return false;
830+
// Nope, not handled. Potentially that's a problem...
831+
if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
832+
p.skipChildren();
833+
return true;
834+
}
835+
// Do we know properties that are expected instead?
836+
Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
837+
throw UnrecognizedPropertyException.from(_parser,
838+
instanceOrClass, propName, propIds);
833839
}
834840

835841
/**
@@ -845,7 +851,7 @@ public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
845851
*
846852
* @return Key value to use
847853
*
848-
* @throws JsonMappingException
854+
* @throws IOException
849855
*
850856
* @since 2.8
851857
*/
@@ -858,17 +864,36 @@ public Object handleWeirdKey(Class<?> keyClass, String keyValue,
858864
msg = String.format(msg, msgArgs);
859865
}
860866
LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
861-
if (h != null) {
862-
while (h != null) {
863-
// Can bail out if it's handled
864-
Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
865-
if (key != DeserializationProblemHandler.NOT_HANDLED) {
866-
return key;
867+
while (h != null) {
868+
// Can bail out if it's handled
869+
Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
870+
if (key != DeserializationProblemHandler.NOT_HANDLED) {
871+
return key;
872+
}
873+
h = h.next();
874+
}
875+
throw weirdKeyException(keyClass, keyValue, msg);
876+
}
877+
878+
/**
879+
* @since 2.8
880+
*/
881+
public JavaType handleUnknownTypeId(JavaType baseType, String id,
882+
String extraDesc) throws IOException
883+
{
884+
LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
885+
while (h != null) {
886+
// Can bail out if it's handled
887+
JavaType type = h.value().handleUnknownTypeId(this, baseType, id, extraDesc);
888+
if (type != null) {
889+
if (type.hasRawClass(Void.class)) {
890+
return null;
867891
}
868-
h = h.next();
892+
return type;
869893
}
894+
h = h.next();
870895
}
871-
throw this.weirdKeyException(keyClass, keyValue, msg);
896+
throw unknownTypeException(baseType, id, extraDesc);
872897
}
873898

874899
/*
@@ -885,7 +910,10 @@ public Object handleWeirdKey(Class<?> keyClass, String keyValue,
885910
* have been) instantiated
886911
* @param deser Deserializer that had the problem, if called by deserializer
887912
* (or on behalf of one)
913+
*
914+
* @deprecated Since 2.8 call {@link #handleUnknownProperty} instead
888915
*/
916+
@Deprecated
889917
public void reportUnknownProperty(Object instanceOrClass, String fieldName,
890918
JsonDeserializer<?> deser)
891919
throws JsonMappingException
@@ -960,15 +988,6 @@ public JsonMappingException reportWrongTokenException(JsonParser p,
960988
throw wrongTokenException(p, expToken, msg);
961989
}
962990

963-
/**
964-
* @since 2.8
965-
*/
966-
public void reportUnknownTypeException(JavaType type, String id,
967-
String extraDesc) throws JsonMappingException
968-
{
969-
throw unknownTypeException(type, id, extraDesc);
970-
}
971-
972991
/**
973992
* @since 2.8
974993
*/
@@ -1151,7 +1170,7 @@ public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken
11511170
/**
11521171
* @since 2.5
11531172
*
1154-
* @deprecated Since 2.8 use {@link #reportUnknownTypeException} instead
1173+
* @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead
11551174
*/
11561175
@Deprecated
11571176
public JsonMappingException unknownTypeException(JavaType type, String id,

src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.fasterxml.jackson.core.JsonParser;
66
import com.fasterxml.jackson.databind.DeserializationConfig;
77
import com.fasterxml.jackson.databind.DeserializationContext;
8+
import com.fasterxml.jackson.databind.JavaType;
89
import com.fasterxml.jackson.databind.JsonDeserializer;
910
import com.fasterxml.jackson.databind.ObjectMapper;
1011

@@ -73,8 +74,8 @@ public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p,
7374

7475
/**
7576
* Method called when a property name from input can not be converted to a
76-
* non-Java-String key type (passed as <code>rawKeyType</code>) due to format
77-
* problem. Handler may choose to do one of 3 things:
77+
* non-Java-String key type (passed as <code>rawKeyType</code>) due to format problem.
78+
* Handler may choose to do one of 3 things:
7879
*<ul>
7980
* <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED}
8081
* </li>
@@ -85,15 +86,15 @@ public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p,
8586
* </li>
8687
* </ul>
8788
*
88-
* @since 2.8
89-
*
9089
* @param failureMsg Message that will be used by caller (by calling
9190
* {@link DeserializationContext#weirdKeyException(Class, String, String)})
9291
* to indicate type of failure unless handler produces key to use
9392
*
9493
* @return Either {@link #NOT_HANDLED} to indicate that handler does not know
9594
* what to do (and exception may be thrown), or value to use as key (possibly
9695
* <code>null</code>
96+
*
97+
* @since 2.8
9798
*/
9899
public Object handleWeirdKey(DeserializationContext ctxt,
99100
Class<?> rawKeyType, String keyValue,
@@ -102,4 +103,42 @@ public Object handleWeirdKey(DeserializationContext ctxt,
102103
{
103104
return NOT_HANDLED;
104105
}
106+
107+
/**
108+
* Handler method called if resolution of type id from given String failed
109+
* to produce a subtype; usually because logical id is not mapped to actual
110+
* implementation class.
111+
* Handler may choose to do one of following things:
112+
*<ul>
113+
* <li>Indicate it does not know what to do by returning `null`
114+
* </li>
115+
* <li>Indicate that nothing should be deserialized, by return `Void.class`
116+
* </li>
117+
* <li>Throw a {@link IOException} to indicate specific fail message (instead of
118+
* standard exception caller would throw
119+
* </li>
120+
* <li>Return actual resolved type to use for type id.
121+
* </li>
122+
* </ul>
123+
*
124+
* @param ctxt Deserialization context to use for accessing information or
125+
* constructing exception to throw
126+
* @param baseType Base type to use for resolving subtype id
127+
* @param subTypeId Subtype id that failed to resolve
128+
* @param failureMsg Informational message that would be thrown as part of
129+
* exception, if resolution still fails
130+
*
131+
* @return Actual type to use, if resolved; `null` if handler does not know what
132+
* to do; or `Void.class` to indicate that nothing should be deserialized for
133+
* type with the id (which caller may choose to do... or not)
134+
*
135+
* @since 2.8
136+
*/
137+
public JavaType handleUnknownTypeId(DeserializationContext ctxt,
138+
JavaType baseType, String subTypeId,
139+
String failureMsg)
140+
throws IOException
141+
{
142+
return null;
143+
}
105144
}

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,10 +1084,6 @@ protected Boolean findFormatFeature(DeserializationContext ctxt,
10841084
* Bean property. Method can deal with the problem as it sees fit (ignore,
10851085
* throw exception); but if it does return, it has to skip the matching
10861086
* Json content parser has.
1087-
*<p>
1088-
* NOTE: method signature was changed in version 1.5; explicit JsonParser
1089-
* <b>must</b> be passed since it may be something other than what
1090-
* context has. Prior versions did not include the first parameter.
10911087
*
10921088
* @param p Parser that points to value of the unknown property
10931089
* @param ctxt Context for deserialization; allows access to the parser,
@@ -1107,11 +1103,8 @@ protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt,
11071103
if (ctxt.handleUnknownProperty(p, this, instanceOrClass, propName)) {
11081104
return;
11091105
}
1110-
// Nope, not handled. Potentially that's a problem...
1111-
ctxt.reportUnknownProperty(instanceOrClass, propName, this);
1112-
11131106
/* But if we do get this far, need to skip whatever value we
1114-
* are pointing to now.
1107+
* are pointing to now (although handler is likely to have done that already)
11151108
*/
11161109
p.skipChildren();
11171110
}

src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,14 @@ protected final JsonDeserializer<Object> _findDeserializer(DeserializationContex
152152
// As per [JACKSON-614], use the default impl if no type id available:
153153
deser = _findDefaultImplDeserializer(ctxt);
154154
if (deser == null) {
155-
deser = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType);
155+
// 10-May-2016, tatu: We may get some help...
156+
JavaType actual = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType);
157+
if (actual == null) { // what should this be taken to mean?
158+
// TODO: try to figure out something better
159+
return null;
160+
}
161+
// ... would this actually work?
162+
deser = ctxt.findContextualValueDeserializer(actual, _property);
156163
}
157164
} else {
158165
/* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters,
@@ -254,9 +261,9 @@ protected Object _deserializeWithNativeTypeId(JsonParser jp, DeserializationCont
254261
* should return that deserializer; otherwise throw an exception to indicate
255262
* the problem.
256263
*
257-
* @since 2.5
264+
* @since 2.8
258265
*/
259-
protected JsonDeserializer<Object> _handleUnknownTypeId(DeserializationContext ctxt, String typeId,
266+
protected JavaType _handleUnknownTypeId(DeserializationContext ctxt, String typeId,
260267
TypeIdResolver idResolver, JavaType baseType)
261268
throws IOException
262269
{
@@ -271,7 +278,6 @@ protected JsonDeserializer<Object> _handleUnknownTypeId(DeserializationContext c
271278
} else {
272279
extraDesc = null;
273280
}
274-
ctxt.reportUnknownTypeException(_baseType, typeId, extraDesc);
275-
return null;
281+
return ctxt.handleUnknownTypeId(_baseType, typeId, extraDesc);
276282
}
277283
}

0 commit comments

Comments
 (0)