diff options
author | Tatu Saloranta <tatu.saloranta@iki.fi> | 2016-05-10 20:03:26 -0700 |
---|---|---|
committer | Tatu Saloranta <tatu.saloranta@iki.fi> | 2016-05-10 20:03:26 -0700 |
commit | 33ba4ad08ee2220b62028101b026e29ed4167d52 (patch) | |
tree | e31fca58ab927fd3b77a0d2b2b0e8248701a2423 | |
parent | bd3c3121f1ecdc07f936fff99bbaa9dac42546dd (diff) | |
download | jackson-databind-33ba4ad08ee2220b62028101b026e29ed4167d52.tar.gz |
Added DeserializationContext.handleUnknownTypeId()
4 files changed, 101 insertions, 44 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java index 0c629d769..ec6bbc055 100644 --- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java +++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java @@ -820,16 +820,22 @@ public abstract class DeserializationContext throws IOException { LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers(); - if (h != null) { - while (h != null) { - // Can bail out if it's handled - if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) { - return true; - } - h = h.next(); + while (h != null) { + // Can bail out if it's handled + if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) { + return true; } + h = h.next(); } - return false; + // Nope, not handled. Potentially that's a problem... + if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { + p.skipChildren(); + return true; + } + // Do we know properties that are expected instead? + Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames(); + throw UnrecognizedPropertyException.from(_parser, + instanceOrClass, propName, propIds); } /** @@ -845,7 +851,7 @@ public abstract class DeserializationContext * * @return Key value to use * - * @throws JsonMappingException + * @throws IOException * * @since 2.8 */ @@ -858,17 +864,36 @@ public abstract class DeserializationContext msg = String.format(msg, msgArgs); } LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers(); - if (h != null) { - while (h != null) { - // Can bail out if it's handled - Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg); - if (key != DeserializationProblemHandler.NOT_HANDLED) { - return key; + while (h != null) { + // Can bail out if it's handled + Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg); + if (key != DeserializationProblemHandler.NOT_HANDLED) { + return key; + } + h = h.next(); + } + throw weirdKeyException(keyClass, keyValue, msg); + } + + /** + * @since 2.8 + */ + public JavaType handleUnknownTypeId(JavaType baseType, String id, + String extraDesc) throws IOException + { + LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers(); + while (h != null) { + // Can bail out if it's handled + JavaType type = h.value().handleUnknownTypeId(this, baseType, id, extraDesc); + if (type != null) { + if (type.hasRawClass(Void.class)) { + return null; } - h = h.next(); + return type; } + h = h.next(); } - throw this.weirdKeyException(keyClass, keyValue, msg); + throw unknownTypeException(baseType, id, extraDesc); } /* @@ -885,7 +910,10 @@ public abstract class DeserializationContext * have been) instantiated * @param deser Deserializer that had the problem, if called by deserializer * (or on behalf of one) + * + * @deprecated Since 2.8 call {@link #handleUnknownProperty} instead */ + @Deprecated public void reportUnknownProperty(Object instanceOrClass, String fieldName, JsonDeserializer<?> deser) throws JsonMappingException @@ -963,15 +991,6 @@ public abstract class DeserializationContext /** * @since 2.8 */ - public void reportUnknownTypeException(JavaType type, String id, - String extraDesc) throws JsonMappingException - { - throw unknownTypeException(type, id, extraDesc); - } - - /** - * @since 2.8 - */ public void reportEndOfInputException(Class<?> instClass) throws JsonMappingException { throw endOfInputException(instClass); } @@ -1151,7 +1170,7 @@ public abstract class DeserializationContext /** * @since 2.5 * - * @deprecated Since 2.8 use {@link #reportUnknownTypeException} instead + * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead */ @Deprecated public JsonMappingException unknownTypeException(JavaType type, String id, diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java index 453a16758..22a2d1775 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java @@ -5,6 +5,7 @@ import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; @@ -73,8 +74,8 @@ public abstract class DeserializationProblemHandler /** * Method called when a property name from input can not be converted to a - * non-Java-String key type (passed as <code>rawKeyType</code>) due to format - * problem. Handler may choose to do one of 3 things: + * non-Java-String key type (passed as <code>rawKeyType</code>) due to format problem. + * Handler may choose to do one of 3 things: *<ul> * <li>Indicate it does not know what to do by returning {@link #NOT_HANDLED} * </li> @@ -85,8 +86,6 @@ public abstract class DeserializationProblemHandler * </li> * </ul> * - * @since 2.8 - * * @param failureMsg Message that will be used by caller (by calling * {@link DeserializationContext#weirdKeyException(Class, String, String)}) * to indicate type of failure unless handler produces key to use @@ -94,6 +93,8 @@ public abstract class DeserializationProblemHandler * @return Either {@link #NOT_HANDLED} to indicate that handler does not know * what to do (and exception may be thrown), or value to use as key (possibly * <code>null</code> + * + * @since 2.8 */ public Object handleWeirdKey(DeserializationContext ctxt, Class<?> rawKeyType, String keyValue, @@ -102,4 +103,42 @@ public abstract class DeserializationProblemHandler { return NOT_HANDLED; } + + /** + * Handler method called if resolution of type id from given String failed + * to produce a subtype; usually because logical id is not mapped to actual + * implementation class. + * Handler may choose to do one of following things: + *<ul> + * <li>Indicate it does not know what to do by returning `null` + * </li> + * <li>Indicate that nothing should be deserialized, by return `Void.class` + * </li> + * <li>Throw a {@link IOException} to indicate specific fail message (instead of + * standard exception caller would throw + * </li> + * <li>Return actual resolved type to use for type id. + * </li> + * </ul> + * + * @param ctxt Deserialization context to use for accessing information or + * constructing exception to throw + * @param baseType Base type to use for resolving subtype id + * @param subTypeId Subtype id that failed to resolve + * @param failureMsg Informational message that would be thrown as part of + * exception, if resolution still fails + * + * @return Actual type to use, if resolved; `null` if handler does not know what + * to do; or `Void.class` to indicate that nothing should be deserialized for + * type with the id (which caller may choose to do... or not) + * + * @since 2.8 + */ + public JavaType handleUnknownTypeId(DeserializationContext ctxt, + JavaType baseType, String subTypeId, + String failureMsg) + throws IOException + { + return null; + } } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java index f47d49a93..383a8d3aa 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java @@ -1084,10 +1084,6 @@ public abstract class StdDeserializer<T> * Bean property. Method can deal with the problem as it sees fit (ignore, * throw exception); but if it does return, it has to skip the matching * Json content parser has. - *<p> - * NOTE: method signature was changed in version 1.5; explicit JsonParser - * <b>must</b> be passed since it may be something other than what - * context has. Prior versions did not include the first parameter. * * @param p Parser that points to value of the unknown property * @param ctxt Context for deserialization; allows access to the parser, @@ -1107,11 +1103,8 @@ public abstract class StdDeserializer<T> if (ctxt.handleUnknownProperty(p, this, instanceOrClass, propName)) { return; } - // Nope, not handled. Potentially that's a problem... - ctxt.reportUnknownProperty(instanceOrClass, propName, this); - /* But if we do get this far, need to skip whatever value we - * are pointing to now. + * are pointing to now (although handler is likely to have done that already) */ p.skipChildren(); } diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java index face387cb..57d3d8272 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java @@ -152,7 +152,14 @@ public abstract class TypeDeserializerBase // As per [JACKSON-614], use the default impl if no type id available: deser = _findDefaultImplDeserializer(ctxt); if (deser == null) { - deser = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType); + // 10-May-2016, tatu: We may get some help... + JavaType actual = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType); + if (actual == null) { // what should this be taken to mean? + // TODO: try to figure out something better + return null; + } + // ... would this actually work? + deser = ctxt.findContextualValueDeserializer(actual, _property); } } else { /* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters, @@ -254,9 +261,9 @@ public abstract class TypeDeserializerBase * should return that deserializer; otherwise throw an exception to indicate * the problem. * - * @since 2.5 + * @since 2.8 */ - protected JsonDeserializer<Object> _handleUnknownTypeId(DeserializationContext ctxt, String typeId, + protected JavaType _handleUnknownTypeId(DeserializationContext ctxt, String typeId, TypeIdResolver idResolver, JavaType baseType) throws IOException { @@ -271,7 +278,6 @@ public abstract class TypeDeserializerBase } else { extraDesc = null; } - ctxt.reportUnknownTypeException(_baseType, typeId, extraDesc); - return null; + return ctxt.handleUnknownTypeId(_baseType, typeId, extraDesc); } } |