aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatu Saloranta <tatu.saloranta@iki.fi>2016-05-10 20:03:26 -0700
committerTatu Saloranta <tatu.saloranta@iki.fi>2016-05-10 20:03:26 -0700
commit33ba4ad08ee2220b62028101b026e29ed4167d52 (patch)
treee31fca58ab927fd3b77a0d2b2b0e8248701a2423
parentbd3c3121f1ecdc07f936fff99bbaa9dac42546dd (diff)
downloadjackson-databind-33ba4ad08ee2220b62028101b026e29ed4167d52.tar.gz
Added DeserializationContext.handleUnknownTypeId()
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java73
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java47
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java9
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java16
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);
}
}