T reportBadDefinition(Class> type, String msg) throws JsonMappingEx
/**********************************************************
*/
- /**
- * @since 2.9
- */
protected final String _format(String msg, Object... msgArgs) {
if (msgArgs.length > 0) {
return String.format(msg, msgArgs);
@@ -329,9 +300,6 @@ protected final String _format(String msg, Object... msgArgs) {
return msg;
}
- /**
- * @since 2.9
- */
protected final String _truncate(String desc) {
if (desc == null) {
return "";
@@ -342,9 +310,6 @@ protected final String _truncate(String desc) {
return desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN);
}
- /**
- * @since 2.9
- */
protected String _quotedString(String desc) {
if (desc == null) {
return "[N/A]";
@@ -352,10 +317,7 @@ protected String _quotedString(String desc) {
// !!! should we quote it? (in case there are control chars, linefeeds)
return String.format("\"%s\"", _truncate(desc));
}
-
- /**
- * @since 2.9
- */
+
protected String _colonConcat(String msgBase, String extra) {
if (extra == null) {
return msgBase;
@@ -363,9 +325,6 @@ protected String _colonConcat(String msgBase, String extra) {
return msgBase + ": " + extra;
}
- /**
- * @since 2.9
- */
protected String _desc(String desc) {
if (desc == null) {
return "[N/A]";
diff --git a/src/main/java/com/fasterxml/jackson/databind/DefaultTyping.java b/src/main/java/com/fasterxml/jackson/databind/DefaultTyping.java
new file mode 100644
index 0000000000..bfa9574367
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/DefaultTyping.java
@@ -0,0 +1,59 @@
+package com.fasterxml.jackson.databind;
+
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
+
+/**
+ * Enumeration used with ObjectMapper.enableDefaultTyping()
+ * to specify what kind of types (classes) default typing should
+ * be used for. It will only be used if no explicit type information
+ * is found, but this enumeration further limits subset of those types.
+ *
+ * Since 2.4 there are special exceptions for JSON Tree model
+ * types (sub-types of {@link TreeNode}: default typing is never
+ * applied to them.
+ * Since 2.8 additional checks are made to avoid attempts at default
+ * typing primitive-valued properties.
+ *
+ * NOTE: use of Default Typing can be a potential security risk if incoming
+ * content comes from untrusted sources, and it is recommended that this
+ * is either not done, or, if enabled, use ObjectMapper.setDefaultTyping()
+ * passing a custom {@link TypeResolverBuilder} implementation that white-lists
+ * legal types to use.
+ */
+public enum DefaultTyping {
+ /**
+ * This value means that only properties that have
+ * {@link java.lang.Object} as declared type (including
+ * generic types without explicit type) will use default
+ * typing.
+ */
+ JAVA_LANG_OBJECT,
+
+ /**
+ * Value that means that default typing will be used for
+ * properties with declared type of {@link java.lang.Object}
+ * or an abstract type (abstract class or interface).
+ * Note that this does not include array types.
+ * This does NOT apply to {@link TreeNode} and its subtypes.
+ */
+ OBJECT_AND_NON_CONCRETE,
+
+ /**
+ * Value that means that default typing will be used for
+ * all types covered by {@link #OBJECT_AND_NON_CONCRETE}
+ * plus all array types for them.
+ * This does NOT apply to {@link TreeNode} and its subtypes.
+ */
+ NON_CONCRETE_AND_ARRAYS,
+
+ /**
+ * Value that means that default typing will be used for
+ * all non-final types, with exception of small number of
+ * "natural" types (String, Boolean, Integer, Double), which
+ * can be correctly inferred from JSON; as well as for
+ * all arrays of non-final types.
+ * This does NOT apply to {@link TreeNode} and its subtypes.
+ */
+ NON_FINAL
+}
\ No newline at end of file
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
index 8ff4d1461d..b89ac6cf68 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
@@ -1,14 +1,13 @@
package com.fasterxml.jackson.databind;
-import java.util.*;
-
import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.core.json.JsonReadFeature;
+
import com.fasterxml.jackson.databind.cfg.*;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.introspect.*;
import com.fasterxml.jackson.databind.jsontype.*;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.databind.util.ArrayIterator;
import com.fasterxml.jackson.databind.util.LinkedNode;
import com.fasterxml.jackson.databind.util.RootNameLookup;
@@ -23,33 +22,14 @@
*/
public final class DeserializationConfig
extends MapperConfigBase
- implements java.io.Serializable // since 2.1
+ implements java.io.Serializable
{
- // since 2.9
- private static final long serialVersionUID = 2;
-
- /*
- /**********************************************************
- /* Configured helper objects
- /**********************************************************
- */
-
- /**
- * Linked list that contains all registered problem handlers.
- * Implementation as front-added linked list allows for sharing
- * of the list (tail) without copying the list.
- */
- protected final LinkedNode _problemHandlers;
-
- /**
- * Factory used for constructing {@link com.fasterxml.jackson.databind.JsonNode} instances.
- */
- protected final JsonNodeFactory _nodeFactory;
+ private static final long serialVersionUID = 3L;
/*
- /**********************************************************
- /* Deserialization features
- /**********************************************************
+ /**********************************************************************
+ /* Deserialization, parser, format features
+ /**********************************************************************
*/
/**
@@ -57,151 +37,101 @@ public final class DeserializationConfig
*/
protected final int _deserFeatures;
- /*
- /**********************************************************
- /* Parser features: generic, format-specific
- /**********************************************************
+ /**
+ * States of {@link com.fasterxml.jackson.core.StreamReadFeature}s to enable/disable.
*/
+ protected final int _streamReadFeatures;
/**
- * States of {@link com.fasterxml.jackson.core.JsonParser.Feature}s to enable/disable.
+ * States of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable.
*/
- protected final int _parserFeatures;
+ protected final int _formatReadFeatures;
- /**
- * Bitflag of {@link com.fasterxml.jackson.core.JsonParser.Feature}s to enable/disable
+ /*
+ /**********************************************************************
+ /* Configured helper objects
+ /**********************************************************************
*/
- protected final int _parserFeaturesToChange;
/**
- * States of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable.
- *
- * @since 2.7
+ * Linked list that contains all registered problem handlers.
+ * Implementation as front-added linked list allows for sharing
+ * of the list (tail) without copying the list.
*/
- protected final int _formatReadFeatures;
+ protected final LinkedNode _problemHandlers;
/**
- * Bitflag of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable
+ * List of objects that may be able to resolve abstract types to
+ * concrete types. Used by functionality like "mr Bean" to materialize
+ * types as needed, although may be used for other kinds of defaulting
+ * as well.
*
- * @since 2.7
+ * @since 3.0
*/
- protected final int _formatReadFeaturesToChange;
+ protected final AbstractTypeResolver[] _abstractTypeResolvers;
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, primary constructors for new instances
- /**********************************************************
+ /**********************************************************************
*/
/**
- * Constructor used by ObjectMapper to create default configuration object instance.
+ * @since 3.0
*/
- public DeserializationConfig(BaseSettings base,
- SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames,
- ConfigOverrides configOverrides)
+ public DeserializationConfig(MapperBuilder,?> b, int mapperFeatures,
+ int deserFeatures, int streamReadFeatures, int formatReadFeatures,
+ ConfigOverrides configOverrides,
+ TypeFactory tf, ClassIntrospector classIntr, MixInHandler mixins, SubtypeResolver str,
+ RootNameLookup rootNames,
+ AbstractTypeResolver[] atrs)
{
- super(base, str, mixins, rootNames, configOverrides);
- _deserFeatures = collectFeatureDefaults(DeserializationFeature.class);
- _nodeFactory = JsonNodeFactory.instance;
- _problemHandlers = null;
- _parserFeatures = 0;
- _parserFeaturesToChange = 0;
- _formatReadFeatures = 0;
- _formatReadFeaturesToChange = 0;
- }
-
- /**
- * Copy-constructor used for making a copy used by new {@link ObjectMapper}.
- *
- * @since 2.9
- */
- protected DeserializationConfig(DeserializationConfig src,
- SimpleMixInResolver mixins, RootNameLookup rootNames,
- ConfigOverrides configOverrides)
- {
- super(src, mixins, rootNames, configOverrides);
- _deserFeatures = src._deserFeatures;
- _problemHandlers = src._problemHandlers;
- _nodeFactory = src._nodeFactory;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
- _formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ super(b, mapperFeatures, tf, classIntr, mixins, str, configOverrides, rootNames);
+ _deserFeatures = deserFeatures;
+ _streamReadFeatures = streamReadFeatures;
+ _formatReadFeatures = formatReadFeatures;
+ _problemHandlers = b.deserializationProblemHandlers();
+ _abstractTypeResolvers = atrs;
}
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, secondary constructors to support
/* "mutant factories", with single property changes
- /**********************************************************
+ /**********************************************************************
*/
private DeserializationConfig(DeserializationConfig src,
- int mapperFeatures, int deserFeatures,
- int parserFeatures, int parserFeatureMask,
- int formatFeatures, int formatFeatureMask)
+ int deserFeatures, int streamReadFeatures, int formatReadFeatures)
{
- super(src, mapperFeatures);
+ super(src);
_deserFeatures = deserFeatures;
- _nodeFactory = src._nodeFactory;
- _problemHandlers = src._problemHandlers;
- _parserFeatures = parserFeatures;
- _parserFeaturesToChange = parserFeatureMask;
- _formatReadFeatures = formatFeatures;
- _formatReadFeaturesToChange = formatFeatureMask;
- }
-
- /**
- * Copy constructor used to create a non-shared instance with given mix-in
- * annotation definitions and subtype resolver.
- */
- private DeserializationConfig(DeserializationConfig src, SubtypeResolver str)
- {
- super(src, str);
- _deserFeatures = src._deserFeatures;
- _nodeFactory = src._nodeFactory;
+ _streamReadFeatures = streamReadFeatures;
+ _formatReadFeatures = formatReadFeatures;
_problemHandlers = src._problemHandlers;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
- _formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ _abstractTypeResolvers = src._abstractTypeResolvers;
}
private DeserializationConfig(DeserializationConfig src, BaseSettings base)
{
super(src, base);
_deserFeatures = src._deserFeatures;
- _nodeFactory = src._nodeFactory;
- _problemHandlers = src._problemHandlers;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
+ _streamReadFeatures = src._streamReadFeatures;
_formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
- }
-
- private DeserializationConfig(DeserializationConfig src, JsonNodeFactory f)
- {
- super(src);
- _deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
- _nodeFactory = f;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
- _formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ _abstractTypeResolvers = src._abstractTypeResolvers;
}
private DeserializationConfig(DeserializationConfig src,
- LinkedNode problemHandlers)
+ LinkedNode problemHandlers,
+ AbstractTypeResolver[] atr)
{
super(src);
_deserFeatures = src._deserFeatures;
- _problemHandlers = problemHandlers;
- _nodeFactory = src._nodeFactory;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
+ _streamReadFeatures = src._streamReadFeatures;
_formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ _problemHandlers = problemHandlers;
+ _abstractTypeResolvers = atr;
}
private DeserializationConfig(DeserializationConfig src, PropertyName rootName)
@@ -209,11 +139,9 @@ private DeserializationConfig(DeserializationConfig src, PropertyName rootName)
super(src, rootName);
_deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
- _nodeFactory = src._nodeFactory;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
+ _streamReadFeatures = src._streamReadFeatures;
_formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ _abstractTypeResolvers = src._abstractTypeResolvers;
}
private DeserializationConfig(DeserializationConfig src, Class> view)
@@ -221,11 +149,9 @@ private DeserializationConfig(DeserializationConfig src, Class> view)
super(src, view);
_deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
- _nodeFactory = src._nodeFactory;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
+ _streamReadFeatures = src._streamReadFeatures;
_formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ _abstractTypeResolvers = src._abstractTypeResolvers;
}
protected DeserializationConfig(DeserializationConfig src, ContextAttributes attrs)
@@ -233,57 +159,31 @@ protected DeserializationConfig(DeserializationConfig src, ContextAttributes att
super(src, attrs);
_deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
- _nodeFactory = src._nodeFactory;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
+ _streamReadFeatures = src._streamReadFeatures;
_formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
- }
-
- protected DeserializationConfig(DeserializationConfig src, SimpleMixInResolver mixins)
- {
- super(src, mixins);
- _deserFeatures = src._deserFeatures;
- _problemHandlers = src._problemHandlers;
- _nodeFactory = src._nodeFactory;
- _parserFeatures = src._parserFeatures;
- _parserFeaturesToChange = src._parserFeaturesToChange;
- _formatReadFeatures = src._formatReadFeatures;
- _formatReadFeaturesToChange = src._formatReadFeaturesToChange;
+ _abstractTypeResolvers = src._abstractTypeResolvers;
}
// for unit tests only:
protected BaseSettings getBaseSettings() { return _base; }
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, general factory methods from MapperConfig(Base)
- /**********************************************************
+ /**********************************************************************
*/
- @Override // since 2.9
+ @Override
protected final DeserializationConfig _withBase(BaseSettings newBase) {
return (_base == newBase) ? this : new DeserializationConfig(this, newBase);
}
- @Override // since 2.9
- protected final DeserializationConfig _withMapperFeatures(int mapperFeatures) {
- return new DeserializationConfig(this, mapperFeatures, _deserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
- }
-
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, specific factory methods from MapperConfig
- /**********************************************************
+ /**********************************************************************
*/
- @Override
- public DeserializationConfig with(SubtypeResolver str) {
- return (_subtypeResolver == str) ? this : new DeserializationConfig(this, str);
- }
-
@Override
public DeserializationConfig withRootName(PropertyName rootName) {
if (rootName == null) {
@@ -307,9 +207,9 @@ public DeserializationConfig with(ContextAttributes attrs) {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, DeserializationFeature-based factory methods
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -320,9 +220,8 @@ public DeserializationConfig with(DeserializationFeature feature)
{
int newDeserFeatures = (_deserFeatures | feature.getMask());
return (newDeserFeatures == _deserFeatures) ? this :
- new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ new DeserializationConfig(this, newDeserFeatures, _streamReadFeatures,
+ _formatReadFeatures);
}
/**
@@ -337,9 +236,8 @@ public DeserializationConfig with(DeserializationFeature first,
newDeserFeatures |= f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
- new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ new DeserializationConfig(this, newDeserFeatures, _streamReadFeatures,
+ _formatReadFeatures);
}
/**
@@ -353,9 +251,8 @@ public DeserializationConfig withFeatures(DeserializationFeature... features)
newDeserFeatures |= f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
- new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ new DeserializationConfig(this, newDeserFeatures,
+ _streamReadFeatures, _formatReadFeatures);
}
/**
@@ -366,9 +263,8 @@ public DeserializationConfig without(DeserializationFeature feature)
{
int newDeserFeatures = _deserFeatures & ~feature.getMask();
return (newDeserFeatures == _deserFeatures) ? this :
- new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ new DeserializationConfig(this, newDeserFeatures,
+ _streamReadFeatures, _formatReadFeatures);
}
/**
@@ -383,9 +279,8 @@ public DeserializationConfig without(DeserializationFeature first,
newDeserFeatures &= ~f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
- new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ new DeserializationConfig(this, newDeserFeatures, _streamReadFeatures,
+ _formatReadFeatures);
}
/**
@@ -399,257 +294,134 @@ public DeserializationConfig withoutFeatures(DeserializationFeature... features)
newDeserFeatures &= ~f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
- new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ new DeserializationConfig(this,
+ newDeserFeatures, _streamReadFeatures, _formatReadFeatures);
}
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, JsonParser.Feature-based factory methods
- /**********************************************************
+ /**********************************************************************
*/
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
- *
- * @since 2.5
*/
- public DeserializationConfig with(JsonParser.Feature feature)
+ public DeserializationConfig with(StreamReadFeature feature)
{
- int newSet = _parserFeatures | feature.getMask();
- int newMask = _parserFeaturesToChange | feature.getMask();
- return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- newSet, newMask,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ int newSet = _streamReadFeatures | feature.getMask();
+ return (_streamReadFeatures == newSet)? this :
+ new DeserializationConfig(this,
+ _deserFeatures, newSet, _formatReadFeatures);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
- *
- * @since 2.5
*/
- public DeserializationConfig withFeatures(JsonParser.Feature... features)
+ public DeserializationConfig withFeatures(StreamReadFeature... features)
{
- int newSet = _parserFeatures;
- int newMask = _parserFeaturesToChange;
- for (JsonParser.Feature f : features) {
- int mask = f.getMask();
- newSet |= mask;
- newMask |= mask;
+ int newSet = _streamReadFeatures;
+ for (StreamReadFeature f : features) {
+ newSet |= f.getMask();
}
- return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- newSet, newMask,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ return (_streamReadFeatures == newSet) ? this :
+ new DeserializationConfig(this, _deserFeatures, newSet,
+ _formatReadFeatures);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified feature disabled.
- *
- * @since 2.5
*/
- public DeserializationConfig without(JsonParser.Feature feature)
+ public DeserializationConfig without(StreamReadFeature feature)
{
- int newSet = _parserFeatures & ~feature.getMask();
- int newMask = _parserFeaturesToChange | feature.getMask();
- return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- newSet, newMask,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ int newSet = _streamReadFeatures & ~feature.getMask();
+ return (_streamReadFeatures == newSet) ? this :
+ new DeserializationConfig(this, _deserFeatures, newSet,
+ _formatReadFeatures);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features disabled.
- *
- * @since 2.5
*/
- public DeserializationConfig withoutFeatures(JsonParser.Feature... features)
+ public DeserializationConfig withoutFeatures(StreamReadFeature... features)
{
- int newSet = _parserFeatures;
- int newMask = _parserFeaturesToChange;
- for (JsonParser.Feature f : features) {
- int mask = f.getMask();
- newSet &= ~mask;
- newMask |= mask;
+ int newSet = _streamReadFeatures;
+ for (StreamReadFeature f : features) {
+ newSet &= ~f.getMask();
}
- return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- newSet, newMask,
- _formatReadFeatures, _formatReadFeaturesToChange);
+ return (_streamReadFeatures == newSet)? this :
+ new DeserializationConfig(this, _deserFeatures, newSet, _formatReadFeatures);
}
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, JsonParser.FormatFeature-based factory methods
- /**********************************************************
+ /**********************************************************************
*/
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
- *
- * @since 2.7
*/
public DeserializationConfig with(FormatFeature feature)
{
- // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
- if (feature instanceof JsonReadFeature) {
- return _withJsonReadFeatures(feature);
- }
int newSet = _formatReadFeatures | feature.getMask();
- int newMask = _formatReadFeaturesToChange | feature.getMask();
- return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- newSet, newMask);
+ return (_formatReadFeatures == newSet) ? this
+ : new DeserializationConfig(this,
+ _deserFeatures, _streamReadFeatures, newSet);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
- *
- * @since 2.7
*/
public DeserializationConfig withFeatures(FormatFeature... features)
{
- // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
- if (features.length > 0 && (features[0] instanceof JsonReadFeature)) {
- return _withJsonReadFeatures(features);
- }
int newSet = _formatReadFeatures;
- int newMask = _formatReadFeaturesToChange;
for (FormatFeature f : features) {
- int mask = f.getMask();
- newSet |= mask;
- newMask |= mask;
+ newSet |= f.getMask();
}
- return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- newSet, newMask);
+ return (_formatReadFeatures == newSet) ? this
+ : new DeserializationConfig(this,
+ _deserFeatures, _streamReadFeatures, newSet);
}
-
+
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified feature disabled.
- *
- * @since 2.7
*/
public DeserializationConfig without(FormatFeature feature)
{
- // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
- if (feature instanceof JsonReadFeature) {
- return _withoutJsonReadFeatures(feature);
- }
int newSet = _formatReadFeatures & ~feature.getMask();
- int newMask = _formatReadFeaturesToChange | feature.getMask();
- return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- newSet, newMask);
+ return (_formatReadFeatures == newSet) ? this
+ : new DeserializationConfig(this,
+ _deserFeatures, _streamReadFeatures, newSet);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features disabled.
- *
- * @since 2.7
*/
public DeserializationConfig withoutFeatures(FormatFeature... features)
{
- // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
- if (features.length > 0 && (features[0] instanceof JsonReadFeature)) {
- return _withoutJsonReadFeatures(features);
- }
- int newSet = _formatReadFeatures;
- int newMask = _formatReadFeaturesToChange;
- for (FormatFeature f : features) {
- int mask = f.getMask();
- newSet &= ~mask;
- newMask |= mask;
- }
- return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- _parserFeatures, _parserFeaturesToChange,
- newSet, newMask);
- }
-
- // temporary for 2.10
- private DeserializationConfig _withJsonReadFeatures(FormatFeature... features) {
- int parserSet = _parserFeatures;
- int parserMask = _parserFeaturesToChange;
int newSet = _formatReadFeatures;
- int newMask = _formatReadFeaturesToChange;
for (FormatFeature f : features) {
- final int mask = f.getMask();
- newSet |= mask;
- newMask |= mask;
-
- if (f instanceof JsonReadFeature) {
- JsonParser.Feature oldF = ((JsonReadFeature) f).mappedFeature();
- if (oldF != null) {
- final int pmask = oldF.getMask();
- parserSet |= pmask;
- parserMask |= pmask;
- }
- }
- }
- return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)
- && (_parserFeatures == parserSet) && (_parserFeaturesToChange == parserMask)
- ) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- parserSet, parserMask, newSet, newMask);
- }
-
- // temporary for 2.10
- private DeserializationConfig _withoutJsonReadFeatures(FormatFeature... features) {
- int parserSet = _parserFeatures;
- int parserMask = _parserFeaturesToChange;
- int newSet = _formatReadFeatures;
- int newMask = _formatReadFeaturesToChange;
- for (FormatFeature f : features) {
- final int mask = f.getMask();
- newSet &= ~mask;
- newMask |= mask;
-
- if (f instanceof JsonReadFeature) {
- JsonParser.Feature oldF = ((JsonReadFeature) f).mappedFeature();
- if (oldF != null) {
- final int pmask = oldF.getMask();
- parserSet &= ~pmask;
- parserMask |= pmask;
- }
- }
+ newSet &= ~f.getMask();
}
- return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)
- && (_parserFeatures == parserSet) && (_parserFeaturesToChange == parserMask)
- ) ? this :
- new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
- parserSet, parserMask, newSet, newMask);
+ return (_formatReadFeatures == newSet) ? this
+ : new DeserializationConfig(this,
+ _deserFeatures, _streamReadFeatures, newSet);
}
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle, deserialization-specific factory methods
- /**********************************************************
- */
-
- /**
- * Fluent factory method that will construct a new instance with
- * specified {@link JsonNodeFactory}
+ /**********************************************************************
*/
- public DeserializationConfig with(JsonNodeFactory f) {
- if (_nodeFactory == f) {
- return this;
- }
- return new DeserializationConfig(this, f);
- }
/**
* Method that can be used to add a handler that can (try to)
@@ -658,11 +430,10 @@ public DeserializationConfig with(JsonNodeFactory f) {
public DeserializationConfig withHandler(DeserializationProblemHandler h)
{
// Sanity check: let's prevent adding same handler multiple times
- if (LinkedNode.contains(_problemHandlers, h)) {
- return this;
- }
- return new DeserializationConfig(this,
- new LinkedNode(h, _problemHandlers));
+ return LinkedNode.contains(_problemHandlers, h) ? this
+ : new DeserializationConfig(this,
+ new LinkedNode(h, _problemHandlers),
+ _abstractTypeResolvers);
}
/**
@@ -670,39 +441,35 @@ public DeserializationConfig withHandler(DeserializationProblemHandler h)
* existing handler(s) with different one(s)
*/
public DeserializationConfig withNoProblemHandlers() {
- if (_problemHandlers == null) {
- return this;
- }
- return new DeserializationConfig(this,
- (LinkedNode) null);
+ return (_problemHandlers == null) ? this
+ : new DeserializationConfig(this,
+ (LinkedNode) null, _abstractTypeResolvers);
}
/*
- /**********************************************************
- /* JsonParser initialization
- /**********************************************************
+ /**********************************************************************
+ /* Support for ObjectReadContext
+ /**********************************************************************
*/
/**
- * Method called by {@link ObjectMapper} and {@link ObjectReader}
- * to modify those {@link com.fasterxml.jackson.core.JsonParser.Feature} settings
- * that have been configured via this config instance.
- *
- * @since 2.5
+ * @since 3.0
*/
- public void initialize(JsonParser p) {
- if (_parserFeaturesToChange != 0) {
- p.overrideStdFeatures(_parserFeatures, _parserFeaturesToChange);
- }
- if (_formatReadFeaturesToChange != 0) {
- p.overrideFormatFeatures(_formatReadFeatures, _formatReadFeaturesToChange);
- }
+ public int getStreamReadFeatures() {
+ return _streamReadFeatures;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public int getFormatReadFeatures() {
+ return _formatReadFeatures;
}
/*
- /**********************************************************
+ /**********************************************************************
/* MapperConfig implementation/overrides: other
- /**********************************************************
+ /**********************************************************************
*/
@Override
@@ -718,19 +485,17 @@ public final boolean isEnabled(DeserializationFeature f) {
return (_deserFeatures & f.getMask()) != 0;
}
- public final boolean isEnabled(JsonParser.Feature f, JsonFactory factory) {
- int mask = f.getMask();
- if ((_parserFeaturesToChange & mask) != 0) {
- return (_parserFeatures & f.getMask()) != 0;
- }
- return factory.isEnabled(f);
+ public final boolean isEnabled(StreamReadFeature f) {
+ return (_streamReadFeatures & f.getMask()) != 0;
}
+ public final boolean hasFormatFeature(FormatFeature f) {
+ return (_formatReadFeatures & f.getMask()) != 0;
+ }
+
/**
* Bulk access method for checking that all features specified by
* mask are enabled.
- *
- * @since 2.3
*/
public final boolean hasDeserializationFeatures(int featureMask) {
return (_deserFeatures & featureMask) == featureMask;
@@ -739,8 +504,6 @@ public final boolean hasDeserializationFeatures(int featureMask) {
/**
* Bulk access method for checking that at least one of features specified by
* mask is enabled.
- *
- * @since 2.6
*/
public final boolean hasSomeOfFeatures(int featureMask) {
return (_deserFeatures & featureMask) != 0;
@@ -755,21 +518,78 @@ public final int getDeserializationFeatures() {
}
/**
- * Convenience method equivalant to:
+ * Convenience method equivalent to:
*
* isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
*
- *
- * @since 2.9
*/
public final boolean requiresFullValue() {
return DeserializationFeature.FAIL_ON_TRAILING_TOKENS.enabledIn(_deserFeatures);
}
/*
- /**********************************************************
+ /**********************************************************************
+ /* Abstract type mapping
+ /**********************************************************************
+ */
+
+ /**
+ * @since 3.0
+ */
+ public boolean hasAbstractTypeResolvers() { return _abstractTypeResolvers.length > 0; }
+
+ /**
+ * @since 3.0
+ */
+ public Iterable abstractTypeResolvers() {
+ return new ArrayIterator(_abstractTypeResolvers);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public JavaType mapAbstractType(JavaType type)
+ {
+ if (!hasAbstractTypeResolvers()) {
+ return type;
+ }
+ // first, general mappings
+ while (true) {
+ JavaType next = _mapAbstractType2(type);
+ if (next == null) {
+ return type;
+ }
+ // Should not have to worry about cycles; but better verify since they will invariably occur... :-)
+ // (also: guard against invalid resolution to a non-related type)
+ Class> prevCls = type.getRawClass();
+ Class> nextCls = next.getRawClass();
+ if ((prevCls == nextCls) || !prevCls.isAssignableFrom(nextCls)) {
+ throw new IllegalArgumentException("Invalid abstract type resolution from "+type+" to "+next+": latter is not a subtype of former");
+ }
+ type = next;
+ }
+ }
+
+ /**
+ * Method that will find abstract type mapping for specified type, doing a single
+ * lookup through registered abstract type resolvers; will not do recursive lookups.
+ */
+ private JavaType _mapAbstractType2(JavaType type)
+ {
+ Class> currClass = type.getRawClass();
+ for (AbstractTypeResolver resolver : abstractTypeResolvers()) {
+ JavaType concrete = resolver.findTypeMapping(this, type);
+ if ((concrete != null) && !concrete.hasRawClass(currClass)) {
+ return concrete;
+ }
+ }
+ return null;
+ }
+
+ /*
+ /**********************************************************************
/* Other configuration
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -779,15 +599,11 @@ public final boolean requiresFullValue() {
public LinkedNode getProblemHandlers() {
return _problemHandlers;
}
-
- public final JsonNodeFactory getNodeFactory() {
- return _nodeFactory;
- }
-
+
/*
- /**********************************************************
+ /**********************************************************************
/* Introspection methods
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -796,60 +612,19 @@ public final JsonNodeFactory getNodeFactory() {
*
* @param type Type of class to be introspected
*/
- @SuppressWarnings("unchecked")
- public T introspect(JavaType type) {
- return (T) getClassIntrospector().forDeserialization(this, type, this);
+ public BeanDescription introspect(JavaType type) {
+ return getClassIntrospector().forDeserialization(this, type, this);
}
/**
* Method that will introspect subset of bean properties needed to
* construct bean instance.
*/
- @SuppressWarnings("unchecked")
- public T introspectForCreation(JavaType type) {
- return (T) getClassIntrospector().forCreation(this, type, this);
+ public BeanDescription introspectForCreation(JavaType type) {
+ return getClassIntrospector().forCreation(this, type, this);
}
- /**
- * @since 2.0
- */
- @SuppressWarnings("unchecked")
- public T introspectForBuilder(JavaType type) {
- return (T) getClassIntrospector().forDeserializationWithBuilder(this, type, this);
- }
-
- /*
- /**********************************************************
- /* Support for polymorphic type handling
- /**********************************************************
- */
-
- /**
- * Helper method that is needed to properly handle polymorphic referenced
- * types, such as types referenced by {@link java.util.concurrent.atomic.AtomicReference},
- * or various "optional" types.
- *
- * @since 2.4
- */
- public TypeDeserializer findTypeDeserializer(JavaType baseType)
- throws JsonMappingException
- {
- BeanDescription bean = introspectClassAnnotations(baseType.getRawClass());
- AnnotatedClass ac = bean.getClassInfo();
- TypeResolverBuilder> b = getAnnotationIntrospector().findTypeResolver(this, ac, baseType);
-
- /* Ok: if there is no explicit type info handler, we may want to
- * use a default. If so, config object knows what to use.
- */
- Collection subtypes = null;
- if (b == null) {
- b = getDefaultTyper(baseType);
- if (b == null) {
- return null;
- }
- } else {
- subtypes = getSubtypeResolver().collectAndResolveSubtypesByTypeId(this, ac);
- }
- return b.buildTypeDeserializer(this, baseType, subtypes);
+ public BeanDescription introspectForBuilder(JavaType type) {
+ return getClassIntrospector().forDeserializationWithBuilder(this, type, this);
}
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
index 040ab092ed..9e00ee4624 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
@@ -4,14 +4,16 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdResolver;
import com.fasterxml.jackson.core.*;
-
+import com.fasterxml.jackson.core.tree.ArrayTreeNode;
+import com.fasterxml.jackson.core.tree.ObjectTreeNode;
+import com.fasterxml.jackson.core.type.ResolvedType;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.cfg.ContextAttributes;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
@@ -24,6 +26,7 @@
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
@@ -35,88 +38,87 @@
* Context for the process of deserialization a single root-level value.
* Used to allow passing in configuration settings and reusable temporary
* objects (scrap arrays, containers).
- *
- * Instance life-cycle is such that a partially configured "blueprint" object
- * is registered with {@link ObjectMapper} (and {@link ObjectReader},
- * and when actual instance is needed for deserialization,
- * a fully configured instance will be created using a method in extended internal
- * API of sub-class
- * ({@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#createInstance}).
- * Each instance is guaranteed to only be used from single-threaded context;
- * instances may be reused if (and only if) no configuration has changed.
- *
- * Defined as abstract class so that implementations must define methods
- * for reconfiguring blueprints and creating instances.
+ * Constructed by {@link ObjectMapper} (and {@link ObjectReader} based on
+ * configuration,
+ * used mostly by {@link JsonDeserializer}s to access contextual information.
*/
public abstract class DeserializationContext
extends DatabindContext
- implements java.io.Serializable
+ implements ObjectReadContext // 3.0
{
- private static final long serialVersionUID = 1L; // 2.6
-
/*
- /**********************************************************
- /* Configuration, immutable
- /**********************************************************
- */
-
- /**
- * Object that handle details of {@link JsonDeserializer} caching.
+ /**********************************************************************
+ /* Per-mapper configuration (immutable via ObjectReader)
+ /**********************************************************************
*/
- protected final DeserializerCache _cache;
- /*
- /**********************************************************
- /* Configuration, changeable via fluent factories
- /**********************************************************
+ /**
+ * Low-level {@link TokenStreamFactory} that may be used for constructing
+ * embedded parsers.
*/
+ final protected TokenStreamFactory _streamFactory;
/**
* Read-only factory instance; exposed to let
* owners (ObjectMapper
, ObjectReader
)
* access it.
*/
- protected final DeserializerFactory _factory;
+ final protected DeserializerFactory _factory;
+
+ /**
+ * Object that handle details of {@link JsonDeserializer} caching.
+ */
+ final protected DeserializerCache _cache;
/*
- /**********************************************************
- /* Configuration that gets set for instances (not blueprints)
- /* (partly denormalized for performance)
- /**********************************************************
+ /**********************************************************************
+ /* Configuration that may vary by ObjectReader
+ /**********************************************************************
*/
/**
* Generic deserialization processing configuration
*/
- protected final DeserializationConfig _config;
+ final protected DeserializationConfig _config;
/**
* Bitmap of {@link DeserializationFeature}s that are enabled
*/
- protected final int _featureFlags;
+ final protected int _featureFlags;
/**
* Currently active view, if any.
*/
- protected final Class> _view;
+ final protected Class> _activeView;
/**
- * Currently active parser used for deserialization.
- * May be different from the outermost parser
- * when content is buffered.
+ * Schema for underlying parser to use, if any.
*/
- protected transient JsonParser _parser;
-
+ final protected FormatSchema _schema;
+
/**
* Object used for resolving references to injectable
* values.
*/
- protected final InjectableValues _injectableValues;
-
+ final protected InjectableValues _injectableValues;
+
/*
- /**********************************************************
+ /**********************************************************************
+ /* Other State
+ /**********************************************************************
+ */
+
+ /**
+ * Currently active parser used for deserialization.
+ * May be different from the outermost parser
+ * when content is buffered.
+ */
+ protected transient JsonParser _parser;
+
+ /*
+ /**********************************************************************
/* Per-operation reusable helper objects (not for blueprints)
- /**********************************************************
+ /**********************************************************************
*/
protected transient ArrayBuilders _arrayBuilders;
@@ -127,104 +129,50 @@ public abstract class DeserializationContext
/**
* Lazily-constructed holder for per-call attributes.
- *
- * @since 2.3
*/
protected transient ContextAttributes _attributes;
/**
- * Type of {@link JsonDeserializer} (or, more specifically,
- * {@link ContextualDeserializer}) that is being
- * contextualized currently.
- *
- * @since 2.5
+ * Type of {@link JsonDeserializer} on which {@link JsonDeserializer#createContextual}
+ * is being called currently.
*/
protected LinkedNode _currentType;
-
+
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle
- /**********************************************************
+ /**********************************************************************
*/
- protected DeserializationContext(DeserializerFactory df) {
- this(df, null);
- }
-
- protected DeserializationContext(DeserializerFactory df,
- DeserializerCache cache)
+ protected DeserializationContext(TokenStreamFactory streamFactory,
+ DeserializerFactory df, DeserializerCache cache,
+ DeserializationConfig config, FormatSchema schema,
+ InjectableValues injectableValues)
{
- if (df == null) {
- throw new IllegalArgumentException("Cannot pass null DeserializerFactory");
- }
+ _streamFactory = streamFactory;
_factory = df;
- if (cache == null) {
- cache = new DeserializerCache();
- }
_cache = cache;
- _featureFlags = 0;
- _config = null;
- _injectableValues = null;
- _view = null;
- _attributes = null;
- }
-
- protected DeserializationContext(DeserializationContext src,
- DeserializerFactory factory)
- {
- _cache = src._cache;
- _factory = factory;
-
- _config = src._config;
- _featureFlags = src._featureFlags;
- _view = src._view;
- _parser = src._parser;
- _injectableValues = src._injectableValues;
- _attributes = src._attributes;
- }
- /**
- * Constructor used for creating actual per-call instances.
- */
- protected DeserializationContext(DeserializationContext src,
- DeserializationConfig config, JsonParser p,
- InjectableValues injectableValues)
- {
- _cache = src._cache;
- _factory = src._factory;
-
_config = config;
_featureFlags = config.getDeserializationFeatures();
- _view = config.getActiveView();
- _parser = p;
+ _activeView = config.getActiveView();
+ _schema = schema;
+
_injectableValues = injectableValues;
_attributes = config.getAttributes();
}
- /**
- * Copy-constructor for use with copy()
by {@link ObjectMapper#copy()}
- */
- protected DeserializationContext(DeserializationContext src) {
- _cache = new DeserializerCache();
- _factory = src._factory;
-
- _config = src._config;
- _featureFlags = src._featureFlags;
- _view = src._view;
- _injectableValues = null;
- }
-
/*
- /**********************************************************
+ /**********************************************************************
/* DatabindContext implementation
- /**********************************************************
+ /**********************************************************************
*/
@Override
public DeserializationConfig getConfig() { return _config; }
@Override
- public final Class> getActiveView() { return _view; }
+ public final Class> getActiveView() { return _activeView; }
@Override
public final boolean canOverrideAccessModifiers() {
@@ -274,9 +222,9 @@ public TimeZone getTimeZone() {
}
/*
- /**********************************************************
- /* Access to per-call state, like generic attributes (2.3+)
- /**********************************************************
+ /**********************************************************************
+ /* Access to per-call state, like generic attributes
+ /**********************************************************************
*/
@Override
@@ -293,15 +241,13 @@ public DeserializationContext setAttribute(Object key, Object value)
/**
* Accessor to {@link JavaType} of currently contextualized
- * {@link ContextualDeserializer}, if any.
+ * {@link JsonDeserializer}, if any.
* This is sometimes useful for generic {@link JsonDeserializer}s that
* do not get passed (or do not retain) type information when being
* constructed: happens for example for deserializers constructed
* from annotations.
- *
- * @since 2.5
*
- * @return Type of {@link ContextualDeserializer} being contextualized,
+ * @return Type of {@link JsonDeserializer} being contextualized,
* if process is on-going; null if not.
*/
public JavaType getContextualType() {
@@ -309,9 +255,113 @@ public JavaType getContextualType() {
}
/*
- /**********************************************************
+ /**********************************************************************
+ /* ObjectReadContext impl, config access
+ /**********************************************************************
+ */
+
+ @Override
+ public TokenStreamFactory getParserFactory() {
+ return _streamFactory;
+ }
+
+ @Override
+ public FormatSchema getSchema() {
+ return _schema;
+ }
+
+ @Override
+ public int getStreamReadFeatures(int defaults) {
+ return _config.getStreamReadFeatures();
+ }
+
+ @Override
+ public int getFormatReadFeatures(int defaults) {
+ return _config.getFormatReadFeatures();
+ }
+
+ /*
+ /**********************************************************************
+ /* ObjectReadContext impl, Tree creation
+ /**********************************************************************
+ */
+
+ @Override
+ public ArrayTreeNode createArrayNode() {
+ return getNodeFactory().arrayNode();
+ }
+
+ @Override
+ public ObjectTreeNode createObjectNode() {
+ return getNodeFactory().objectNode();
+ }
+
+ /*
+ /**********************************************************************
+ /* ObjectReadContext impl, databind
+ /**********************************************************************
+ */
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T readTree(JsonParser p) throws IOException {
+ // NOTE: inlined version of `_bindAsTree()` from `ObjectReader`
+ JsonToken t = p.currentToken();
+ if (t == null) {
+ t = p.nextToken();
+ if (t == null) { // [databind#1406]: expose end-of-input as `null`
+ return null;
+ }
+ }
+ if (t == JsonToken.VALUE_NULL) {
+ return (T) getNodeFactory().nullNode();
+ }
+ JsonDeserializer deser = findRootValueDeserializer(ObjectReader.JSON_NODE_TYPE);
+ return (T) deser.deserialize(p, this);
+ }
+
+ /**
+ * Convenience method that may be used by composite or container deserializers,
+ * for reading one-off values contained (for sequences, it is more efficient
+ * to actually fetch deserializer once for the whole collection).
+ *
+ * NOTE: when deserializing values of properties contained in composite types,
+ * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)};
+ * this method does not allow use of contextual annotations.
+ */
+ @Override
+ public T readValue(JsonParser p, Class type) throws IOException {
+ return readValue(p, getTypeFactory().constructType(type));
+ }
+
+ @Override
+ public T readValue(JsonParser p, TypeReference refType) throws IOException {
+ return readValue(p, getTypeFactory().constructType(refType));
+ }
+
+ @Override
+ public T readValue(JsonParser p, ResolvedType type) throws IOException {
+ if (!(type instanceof JavaType)) {
+ throw new UnsupportedOperationException(
+"Only support `JavaType` implementation of `ResolvedType`, not: "+type.getClass().getName());
+ }
+ return readValue(p, (JavaType) type);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T readValue(JsonParser p, JavaType type) throws IOException {
+ JsonDeserializer deser = findRootValueDeserializer(type);
+ if (deser == null) {
+ reportBadDefinition(type,
+ "Could not find JsonDeserializer for type "+type);
+ }
+ return (T) deser.deserialize(p, this);
+ }
+
+ /*
+ /**********************************************************************
/* Public API, config setting accessors
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -335,8 +385,6 @@ public final boolean isEnabled(DeserializationFeature feat) {
/**
* Bulk access method for getting the bit mask of all {@link DeserializationFeature}s
* that are enabled.
- *
- * @since 2.6
*/
public final int getDeserializationFeatures() {
return _featureFlags;
@@ -406,34 +454,37 @@ public final JsonNodeFactory getNodeFactory() {
}
/*
- /**********************************************************
- /* Public API, pass-through to DeserializerCache
- /**********************************************************
+ /**********************************************************************
+ /* Introspection support
+ /**********************************************************************
*/
/**
- * Method for checking whether we could find a deserializer
- * for given type.
- *
- * @param type
- * @since 2.3
+ * Convenience method for doing full "for serialization" introspection of specified
+ * type; results may be cached during lifespan of this context as well.
*/
- public boolean hasValueDeserializerFor(JavaType type, AtomicReference cause) {
- try {
- return _cache.hasValueDeserializerFor(this, _factory, type);
- } catch (JsonMappingException e) {
- if (cause != null) {
- cause.set(e);
- }
- } catch (RuntimeException e) {
- if (cause == null) { // earlier behavior
- throw e;
- }
- cause.set(e);
- }
- return false;
+ public BeanDescription introspect(JavaType type) throws JsonMappingException {
+ return _config.introspect(type);
}
-
+
+ public BeanDescription introspectClassAnnotations(JavaType type) throws JsonMappingException {
+ return _config.introspectClassAnnotations(type);
+ }
+
+ public BeanDescription introspectForCreation(JavaType type) throws JsonMappingException{
+ return _config.introspectForCreation(type);
+ }
+
+ public BeanDescription introspectForBuilder(JavaType type) throws JsonMappingException {
+ return _config.introspectForBuilder(type);
+ }
+
+ /*
+ /**********************************************************************
+ /* Public API, value deserializer access
+ /**********************************************************************
+ */
+
/**
* Method for finding a value deserializer, and creating a contextual
* version if necessary, for value reached via specified property.
@@ -454,13 +505,11 @@ public final JsonDeserializer findContextualValueDeserializer(JavaType t
* performing any contextualization (unlike {@link #findContextualValueDeserializer})
* or checking for need to create a {@link TypeDeserializer} (unlike
* {@link #findRootValueDeserializer(JavaType)}.
- * This method is usually called from within {@link ResolvableDeserializer#resolve},
+ * This method is usually called from within {@link JsonDeserializer#resolve},
* and expectation is that caller then calls either
* {@link #handlePrimaryContextualization(JsonDeserializer, BeanProperty, JavaType)} or
* {@link #handleSecondaryContextualization(JsonDeserializer, BeanProperty, JavaType)} at a
* later point, as necessary.
- *
- * @since 2.5
*/
public final JsonDeserializer findNonContextualValueDeserializer(JavaType type)
throws JsonMappingException
@@ -481,7 +530,7 @@ public final JsonDeserializer findRootValueDeserializer(JavaType type)
return null;
}
deser = (JsonDeserializer) handleSecondaryContextualization(deser, null, type);
- TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
+ TypeDeserializer typeDeser = findTypeDeserializer(type);
if (typeDeser != null) {
// important: contextualize to indicate this is for root value
typeDeser = typeDeser.forProperty(null);
@@ -490,14 +539,92 @@ public final JsonDeserializer findRootValueDeserializer(JavaType type)
return deser;
}
+ /*
+ /**********************************************************************
+ /* Public API, value type deserializer access
+ /**********************************************************************
+ */
+
/**
- * Convenience method, functionally same as:
- *
- * getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
- *
+ * Method called to find and create a type information deserializer for given base type,
+ * if one is needed. If not needed (no polymorphic handling configured for type),
+ * should return null.
+ *
+ * Note that this method is usually only directly called for values of container (Collection,
+ * array, Map) types and root values, but not for bean property values.
+ *
+ * @param baseType Declared base type of the value to deserializer (actual
+ * deserializer type will be this type or its subtype)
+ *
+ * @return Type deserializer to use for given base type, if one is needed; null if not.
+ */
+ public TypeDeserializer findTypeDeserializer(JavaType baseType)
+ throws JsonMappingException
+ {
+ return findTypeDeserializer(baseType, introspectClassAnnotations(baseType));
+ }
+
+ public TypeDeserializer findTypeDeserializer(JavaType baseType,
+ BeanDescription beanDesc)
+ throws JsonMappingException
+ {
+ return _config.getTypeResolverProvider().findTypeDeserializer(this,
+ baseType, beanDesc.getClassInfo());
+ }
+
+ /**
+ * Method called to create a type information deserializer for values of
+ * given non-container property, if one is needed.
+ * If not needed (no polymorphic handling configured for property), should return null.
+ *
+ * Note that this method is only called for non-container bean properties,
+ * and not for values in container types or root values (or container properties)
+ *
+ * @param baseType Declared base type of the value to deserializer (actual
+ * deserializer type will be this type or its subtype)
+ *
+ * @return Type deserializer to use for given base type, if one is needed; null if not.
+ *
+ * @since 3.0
*/
+ public TypeDeserializer findPropertyTypeDeserializer(JavaType baseType,
+ AnnotatedMember accessor)
+ throws JsonMappingException
+ {
+ return _config.getTypeResolverProvider().findPropertyTypeDeserializer(this,
+ accessor, baseType);
+ }
+
+ /**
+ * Method called to find and create a type information deserializer for values of
+ * given container (list, array, map) property, if one is needed.
+ * If not needed (no polymorphic handling configured for property), should return null.
+ *
+ * Note that this method is only called for container bean properties,
+ * and not for values in container types or root values (or non-container properties)
+ *
+ * @param containerType Type of property; must be a container type
+ * @param accessor Field or method that contains container property
+ *
+ * @since 3.0
+ */
+ public TypeDeserializer findPropertyContentTypeDeserializer(JavaType containerType,
+ AnnotatedMember accessor)
+ throws JsonMappingException
+ {
+ return _config.getTypeResolverProvider().findPropertyContentTypeDeserializer(this,
+ accessor, containerType);
+ }
+
+ /*
+ /**********************************************************************
+ /* Public API, key deserializer access
+ /**********************************************************************
+ */
+
public final KeyDeserializer findKeyDeserializer(JavaType keyType,
- BeanProperty prop) throws JsonMappingException {
+ BeanProperty prop) throws JsonMappingException
+ {
KeyDeserializer kd = _cache.findKeyDeserializer(this,
_factory, keyType);
// Second: contextualize?
@@ -506,11 +633,11 @@ public final KeyDeserializer findKeyDeserializer(JavaType keyType,
}
return kd;
}
-
+
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, ObjectId handling
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -529,9 +656,9 @@ public abstract void checkUnresolvedObjectId()
throws UnresolvedForwardReference;
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, type handling
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -549,8 +676,6 @@ public final JavaType constructType(Class> cls) {
* Class instance, the reason being that it may be necessary to work around
* various ClassLoader limitations, as well as to handle primitive type
* signatures.
- *
- * @since 2.6
*/
public Class> findClass(String className) throws ClassNotFoundException
{
@@ -559,9 +684,9 @@ public Class> findClass(String className) throws ClassNotFoundException
}
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, helper object recycling
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -611,9 +736,9 @@ public final ArrayBuilders getArrayBuilders()
}
/*
- /**********************************************************
+ /**********************************************************************
/* Extended API: handler instantiation
- /**********************************************************
+ /**********************************************************************
*/
public abstract JsonDeserializer deserializerInstance(Annotated annotated,
@@ -625,31 +750,28 @@ public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
throws JsonMappingException;
/*
- /**********************************************************
+ /**********************************************************************
/* Extended API: resolving contextual deserializers; called
- /* by structured deserializers for their value/component
- /* deserializers
- /**********************************************************
+ /* by structured deserializers for their value/component deserializers
+ /**********************************************************************
*/
/**
* Method called for primary property deserializers (ones
* directly created to deserialize values of a POJO property),
- * to handle details of resolving
- * {@link ContextualDeserializer} with given property context.
+ * to handle details of calling
+ * {@link JsonDeserializer#createContextual} with given property context.
*
* @param prop Property for which the given primary deserializer is used; never null.
- *
- * @since 2.5
*/
public JsonDeserializer> handlePrimaryContextualization(JsonDeserializer> deser,
BeanProperty prop, JavaType type)
throws JsonMappingException
{
- if (deser instanceof ContextualDeserializer) {
+ if (deser != null) {
_currentType = new LinkedNode(type, _currentType);
try {
- deser = ((ContextualDeserializer) deser).createContextual(this, prop);
+ deser = deser.createContextual(this, prop);
} finally {
_currentType = _currentType.next();
}
@@ -663,24 +785,22 @@ public JsonDeserializer> handlePrimaryContextualization(JsonDeserializer> de
* but instead created as a component -- such as value deserializers
* for structured types, or deserializers for root values)
* to handle details of resolving
- * {@link ContextualDeserializer} with given property context.
+ * {@link JsonDeserializer#createContextual} with given property context.
* Given that these deserializers are not directly related to given property
* (or, in case of root value property, to any property), annotations
* accessible may or may not be relevant.
*
* @param prop Property for which deserializer is used, if any; null
* when deserializing root values
- *
- * @since 2.5
*/
public JsonDeserializer> handleSecondaryContextualization(JsonDeserializer> deser,
BeanProperty prop, JavaType type)
throws JsonMappingException
{
- if (deser instanceof ContextualDeserializer) {
+ if (deser != null) {
_currentType = new LinkedNode(type, _currentType);
try {
- deser = ((ContextualDeserializer) deser).createContextual(this, prop);
+ deser =deser.createContextual(this, prop);
} finally {
_currentType = _currentType.next();
}
@@ -689,9 +809,9 @@ public JsonDeserializer> handleSecondaryContextualization(JsonDeserializer>
}
/*
- /**********************************************************
+ /**********************************************************************
/* Parsing methods that may use reusable/-cyclable objects
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -728,54 +848,21 @@ public Calendar constructCalendar(Date d) {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Convenience methods for reading parsed values
- /**********************************************************
+ /**********************************************************************
*/
-
- /**
- * Convenience method that may be used by composite or container deserializers,
- * for reading one-off values contained (for sequences, it is more efficient
- * to actually fetch deserializer once for the whole collection).
- *
- * NOTE: when deserializing values of properties contained in composite types,
- * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)};
- * this method does not allow use of contextual annotations.
- *
- * @since 2.4
- */
- public T readValue(JsonParser p, Class type) throws IOException {
- return readValue(p, getTypeFactory().constructType(type));
- }
-
- /**
- * @since 2.4
- */
- @SuppressWarnings("unchecked")
- public T readValue(JsonParser p, JavaType type) throws IOException {
- JsonDeserializer deser = findRootValueDeserializer(type);
- if (deser == null) {
- reportBadDefinition(type,
- "Could not find JsonDeserializer for type "+type);
- }
- return (T) deser.deserialize(p, this);
- }
-
+
/**
* Convenience method that may be used by composite or container deserializers,
* for reading one-off values for the composite type, taking into account
* annotations that the property (passed to this method -- usually property that
* has custom serializer that called this method) has.
- *
- * @since 2.4
*/
public T readPropertyValue(JsonParser p, BeanProperty prop, Class type) throws IOException {
return readPropertyValue(p, prop, getTypeFactory().constructType(type));
}
- /**
- * @since 2.4
- */
@SuppressWarnings("unchecked")
public T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) throws IOException {
JsonDeserializer deser = findContextualValueDeserializer(type, prop);
@@ -788,9 +875,9 @@ public T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) t
}
/*
- /**********************************************************
+ /**********************************************************************
/* Methods for problem handling
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -841,8 +928,6 @@ public boolean handleUnknownProperty(JsonParser p, JsonDeserializer> deser,
* @return Key value to use
*
* @throws IOException To indicate unrecoverable problem, usually based on msg
- *
- * @since 2.8
*/
public Object handleWeirdKey(Class> keyClass, String keyValue,
String msg, Object... msgArgs)
@@ -885,8 +970,6 @@ public Object handleWeirdKey(Class> keyClass, String keyValue,
* @return Property value to use
*
* @throws IOException To indicate unrecoverable problem, usually based on msg
- *
- * @since 2.8
*/
public Object handleWeirdStringValue(Class> targetClass, String value,
String msg, Object... msgArgs)
@@ -929,8 +1012,6 @@ public Object handleWeirdStringValue(Class> targetClass, String value,
* @return Property value to use
*
* @throws IOException To indicate unrecoverable problem, usually based on msg
- *
- * @since 2.8
*/
public Object handleWeirdNumberValue(Class> targetClass, Number value,
String msg, Object... msgArgs)
@@ -991,8 +1072,6 @@ public Object handleWeirdNativeValue(JavaType targetType, Object badValue,
* @param p Parser that points to the JSON value to decode
*
* @return Object that should be constructed, if any; has to be of type instClass
- *
- * @since 2.9 (2.8 had alternate that did not take ValueInstantiator
)
*/
@SuppressWarnings("resource")
public Object handleMissingInstantiator(Class> instClass, ValueInstantiator valueInst,
@@ -1024,7 +1103,7 @@ public Object handleMissingInstantiator(Class> instClass, ValueInstantiator va
// exists), or input mismatch problem (otherwise) since none of existing creators
// match with token.
if ((valueInst != null) && !valueInst.canInstantiate()) {
- msg = String.format("Cannot construct instance of %s (no Creators, like default construct, exist): %s",
+ msg = String.format("Cannot construct instance of %s (no Creators, like default constructor, exist): %s",
ClassUtil.nameOf(instClass), msg);
return reportBadDefinition(constructType(instClass), msg);
}
@@ -1047,8 +1126,6 @@ public Object handleMissingInstantiator(Class> instClass, ValueInstantiator va
* @param t Exception that caused failure
*
* @return Object that should be constructed, if any; has to be of type instClass
- *
- * @since 2.8
*/
public Object handleInstantiationProblem(Class> instClass, Object argument,
Throwable t)
@@ -1085,13 +1162,11 @@ public Object handleInstantiationProblem(Class> instClass, Object argument,
* @param p Parser that points to the JSON value to decode
*
* @return Object that should be constructed, if any; has to be of type instClass
- *
- * @since 2.8
*/
public Object handleUnexpectedToken(Class> instClass, JsonParser p)
throws IOException
{
- return handleUnexpectedToken(instClass, p.getCurrentToken(), p, null);
+ return handleUnexpectedToken(instClass, p.currentToken(), p, null);
}
/**
@@ -1106,8 +1181,6 @@ public Object handleUnexpectedToken(Class> instClass, JsonParser p)
* @param p Parser that points to the JSON value to decode
*
* @return Object that should be constructed, if any; has to be of type instClass
- *
- * @since 2.8
*/
public Object handleUnexpectedToken(Class> instClass, JsonToken t,
JsonParser p, String msg, Object... msgArgs)
@@ -1158,8 +1231,6 @@ public Object handleUnexpectedToken(Class> instClass, JsonToken t,
*
* @throws IOException To indicate unrecoverable problem, if resolution cannot
* be made to work
- *
- * @since 2.8
*/
public JavaType handleUnknownTypeId(JavaType baseType, String id,
TypeIdResolver idResolver, String extraDesc) throws IOException
@@ -1188,9 +1259,6 @@ public JavaType handleUnknownTypeId(JavaType baseType, String id,
throw invalidTypeIdException(baseType, id, extraDesc);
}
- /**
- * @since 2.9
- */
public JavaType handleMissingTypeId(JavaType baseType,
TypeIdResolver idResolver, String extraDesc) throws IOException
{
@@ -1219,9 +1287,6 @@ public JavaType handleMissingTypeId(JavaType baseType,
throw missingTypeIdException(baseType, extraDesc);
}
- /**
- * @since 2.9.2
- */
protected boolean _isCompatible(Class> target, Object value)
{
if ((value == null) || target.isInstance(value)) {
@@ -1233,10 +1298,10 @@ protected boolean _isCompatible(Class> target, Object value)
}
/*
- /**********************************************************
+ /**********************************************************************
/* Methods for problem reporting, in cases where recovery
/* is not considered possible: input problem
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -1246,8 +1311,6 @@ protected boolean _isCompatible(Class> target, Object value)
* Note that this method will throw a {@link JsonMappingException} and no
* recovery is attempted (via {@link DeserializationProblemHandler}, as
* problem is considered to be difficult to recover from, in general.
- *
- * @since 2.9
*/
public void reportWrongTokenException(JsonDeserializer> deser,
JsonToken expToken, String msg, Object... msgArgs)
@@ -1264,8 +1327,6 @@ public void reportWrongTokenException(JsonDeserializer> deser,
* Note that this method will throw a {@link JsonMappingException} and no
* recovery is attempted (via {@link DeserializationProblemHandler}, as
* problem is considered to be difficult to recover from, in general.
- *
- * @since 2.9
*/
public void reportWrongTokenException(JavaType targetType,
JsonToken expToken, String msg, Object... msgArgs)
@@ -1282,8 +1343,6 @@ public void reportWrongTokenException(JavaType targetType,
* Note that this method will throw a {@link JsonMappingException} and no
* recovery is attempted (via {@link DeserializationProblemHandler}, as
* problem is considered to be difficult to recover from, in general.
- *
- * @since 2.9
*/
public void reportWrongTokenException(Class> targetType,
JsonToken expToken, String msg, Object... msgArgs)
@@ -1293,9 +1352,6 @@ public void reportWrongTokenException(Class> targetType,
throw wrongTokenException(getParser(), targetType, expToken, msg);
}
- /**
- * @since 2.8
- */
public T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
throws JsonMappingException
{
@@ -1307,8 +1363,6 @@ public T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
/**
* Helper method used to indicate a problem with input in cases where more
* specific reportXxx()
method was not available.
- *
- * @since 2.9
*/
public T reportInputMismatch(BeanProperty prop,
String msg, Object... msgArgs) throws JsonMappingException
@@ -1321,8 +1375,6 @@ public T reportInputMismatch(BeanProperty prop,
/**
* Helper method used to indicate a problem with input in cases where more
* specific reportXxx()
method was not available.
- *
- * @since 2.9
*/
public T reportInputMismatch(JsonDeserializer> src,
String msg, Object... msgArgs) throws JsonMappingException
@@ -1334,8 +1386,6 @@ public T reportInputMismatch(JsonDeserializer> src,
/**
* Helper method used to indicate a problem with input in cases where more
* specific reportXxx()
method was not available.
- *
- * @since 2.9
*/
public T reportInputMismatch(Class> targetType,
String msg, Object... msgArgs) throws JsonMappingException
@@ -1347,8 +1397,6 @@ public T reportInputMismatch(Class> targetType,
/**
* Helper method used to indicate a problem with input in cases where more
* specific reportXxx()
method was not available.
- *
- * @since 2.9
*/
public T reportInputMismatch(JavaType targetType,
String msg, Object... msgArgs) throws JsonMappingException
@@ -1366,49 +1414,6 @@ public T reportTrailingTokens(Class> targetType,
));
}
- @Deprecated // since 2.9
- public void reportWrongTokenException(JsonParser p,
- JsonToken expToken, String msg, Object... msgArgs)
- throws JsonMappingException
- {
- msg = _format(msg, msgArgs);
- throw wrongTokenException(p, expToken, msg);
- }
-
- /**
- * Helper method for reporting a problem with unhandled unknown property.
- *
- * @param instanceOrClass Either value being populated (if one has been
- * instantiated), or Class that indicates type that would be (or
- * 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
- {
- if (isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
- // Do we know properties that are expected instead?
- Collection propIds = (deser == null) ? null : deser.getKnownPropertyNames();
- throw UnrecognizedPropertyException.from(_parser,
- instanceOrClass, fieldName, propIds);
- }
- }
-
- /**
- * @since 2.8
- *
- * @deprecated Since 2.9: not clear this ever occurs
- */
- @Deprecated // since 2.9
- public void reportMissingContent(String msg, Object... msgArgs) throws JsonMappingException {
- throw MismatchedInputException.from(getParser(), (JavaType) null, "No content to map due to end-of-input");
- }
-
/*
/**********************************************************
/* Methods for problem reporting, in cases where recovery
@@ -1420,8 +1425,6 @@ public void reportMissingContent(String msg, Object... msgArgs) throws JsonMappi
* Helper method called to indicate problem in POJO (serialization) definitions or settings
* regarding specific Java type, unrelated to actual JSON content to map.
* Default behavior is to construct and throw a {@link JsonMappingException}.
- *
- * @since 2.9
*/
public T reportBadTypeDefinition(BeanDescription bean,
String msg, Object... msgArgs) throws JsonMappingException {
@@ -1435,8 +1438,6 @@ public T reportBadTypeDefinition(BeanDescription bean,
* Helper method called to indicate problem in POJO (serialization) definitions or settings
* regarding specific property (of a type), unrelated to actual JSON content to map.
* Default behavior is to construct and throw a {@link JsonMappingException}.
- *
- * @since 2.9
*/
public T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
String msg, Object... msgArgs) throws JsonMappingException {
@@ -1461,8 +1462,6 @@ public T reportBadDefinition(JavaType type, String msg) throws JsonMappingEx
* Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled,
* this method will simply return null; otherwise {@link InvalidDefinitionException}
* will be thrown.
- *
- * @since 2.9
*/
public T reportBadMerge(JsonDeserializer> deser) throws JsonMappingException
{
@@ -1475,10 +1474,10 @@ public T reportBadMerge(JsonDeserializer> deser) throws JsonMappingExcepti
}
/*
- /**********************************************************
+ /**********************************************************************
/* Methods for constructing semantic exceptions; usually not
/* to be called directly, call `handleXxx()` instead
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -1488,14 +1487,12 @@ public T reportBadMerge(JsonDeserializer> deser) throws JsonMappingExcepti
* Note that most of the time this method should NOT be directly called;
* instead, {@link #reportWrongTokenException} should be called and will
* call this method as necessary.
- *
- * @since 2.9
*/
public JsonMappingException wrongTokenException(JsonParser p, JavaType targetType,
JsonToken expToken, String extra)
{
String msg = String.format("Unexpected token (%s), expected %s",
- p.getCurrentToken(), expToken);
+ p.currentToken(), expToken);
msg = _colonConcat(msg, extra);
return MismatchedInputException.from(p, targetType, msg);
}
@@ -1503,18 +1500,11 @@ public JsonMappingException wrongTokenException(JsonParser p, JavaType targetTyp
public JsonMappingException wrongTokenException(JsonParser p, Class> targetType,
JsonToken expToken, String extra)
{
- String msg = String.format("Unexpected token (%s), expected %s",
- p.getCurrentToken(), expToken);
+ JsonToken t = (p == null) ? null : p.currentToken();
+ String msg = String.format("Unexpected token (%s), expected %s", t, expToken);
msg = _colonConcat(msg, extra);
return MismatchedInputException.from(p, targetType, msg);
}
-
- @Deprecated // since 2.9
- public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken,
- String msg)
- {
- return wrongTokenException(p, (JavaType) null, expToken, msg);
- }
/**
* Helper method for constructing exception to indicate that given JSON
@@ -1542,8 +1532,6 @@ public JsonMappingException weirdKeyException(Class> keyClass, String keyValue
* @param value String value from input being deserialized
* @param instClass Type that String should be deserialized into
* @param msgBase Message that describes specific problem
- *
- * @since 2.1
*/
public JsonMappingException weirdStringException(String value, Class> instClass,
String msgBase) {
@@ -1574,8 +1562,6 @@ public JsonMappingException weirdNumberException(Number value, Class> instClas
* and can not be used to construct value of specified type (usually POJO).
* Note that most of the time this method should NOT be called; instead,
* {@link #handleWeirdNativeValue} should be called which will call this method
- *
- * @since 2.9
*/
public JsonMappingException weirdNativeValueException(Object value, Class> instClass)
{
@@ -1634,9 +1620,6 @@ public JsonMappingException invalidTypeIdException(JavaType baseType, String typ
return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, typeId);
}
- /**
- * @since 2.9
- */
public JsonMappingException missingTypeIdException(JavaType baseType,
String extraDesc) {
String msg = String.format("Missing type id when trying to resolve subtype of %s",
@@ -1645,130 +1628,27 @@ public JsonMappingException missingTypeIdException(JavaType baseType,
}
/*
- /**********************************************************
- /* Deprecated exception factory methods
- /**********************************************************
- */
-
- /**
- * @since 2.5
- *
- * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead
- */
- @Deprecated
- public JsonMappingException unknownTypeException(JavaType type, String id,
- String extraDesc)
- {
- String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
- id, type);
- msg = _colonConcat(msg, extraDesc);
- return MismatchedInputException.from(_parser, type, msg);
- }
-
- /**
- * Helper method for constructing exception to indicate that end-of-input was
- * reached while still expecting more tokens to deserialize value of specified type.
- *
- * @deprecated Since 2.8; currently no way to catch EOF at databind level
- */
- @Deprecated
- public JsonMappingException endOfInputException(Class> instClass) {
- return MismatchedInputException.from(_parser, instClass,
- "Unexpected end-of-input when trying to deserialize a "+instClass.getName());
- }
-
- /*
- /**********************************************************
- /* Deprecated methods for constructing, throwing non-specific
- /* JsonMappingExceptions: as of 2.9, should use more specific
- /* ones.
- /**********************************************************
- */
-
- /**
- * Fallback method that may be called if no other reportXxx
- * is applicable -- but only in that case.
- *
- * @since 2.8
- *
- * @deprecated Since 2.9: use a more specific method, or {@link #reportBadDefinition(JavaType, String)},
- * or {@link #reportInputMismatch} instead
- */
- @Deprecated // since 2.9
- public void reportMappingException(String msg, Object... msgArgs)
- throws JsonMappingException
- {
- throw JsonMappingException.from(getParser(), _format(msg, msgArgs));
- }
-
- /**
- * Helper method for constructing generic mapping exception with specified
- * message and current location information.
- * Note that application code should almost always call
- * one of handleXxx
methods, or {@link #reportMappingException(String, Object...)}
- * instead.
- *
- * @since 2.6
- *
- * @deprecated Since 2.9 use more specific error reporting methods instead
- */
- @Deprecated
- public JsonMappingException mappingException(String message) {
- return JsonMappingException.from(getParser(), message);
- }
-
- /**
- * Helper method for constructing generic mapping exception with specified
- * message and current location information
- * Note that application code should almost always call
- * one of handleXxx
methods, or {@link #reportMappingException(String, Object...)}
- * instead.
- *
- * @since 2.6
- *
- * @deprecated Since 2.9 use more specific error reporting methods instead
- */
- @Deprecated
- public JsonMappingException mappingException(String msg, Object... msgArgs) {
- return JsonMappingException.from(getParser(), _format(msg, msgArgs));
- }
-
- /**
- * Helper method for constructing generic mapping exception for specified type
- *
- * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
+ /**********************************************************************
+ /* Other internal methods
+ /**********************************************************************
*/
- @Deprecated
- public JsonMappingException mappingException(Class> targetClass) {
- return mappingException(targetClass, _parser.getCurrentToken());
- }
/**
- * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
+ * Helper method to get a non-shared instance of {@link DateFormat} with default
+ * configuration; instance is lazily constructed, reused within same instance of
+ * context (that is, within same life-cycle of readValue()
from mapper
+ * or reader). Reuse is safe since access will not occur from multiple threads
+ * (unless caller somehow manages to share context objects across threads which is not
+ * supported).
*/
- @Deprecated
- public JsonMappingException mappingException(Class> targetClass, JsonToken token) {
- return JsonMappingException.from(_parser,
- String.format("Cannot deserialize instance of %s out of %s token",
- ClassUtil.nameOf(targetClass), token));
- }
-
- /*
- /**********************************************************
- /* Other internal methods
- /**********************************************************
- */
-
protected DateFormat getDateFormat()
{
if (_dateFormat != null) {
return _dateFormat;
}
- /* 24-Feb-2012, tatu: At this point, all timezone configuration
- * should have occurred, with respect to default dateformat
- * and timezone configuration. But we still better clone
- * an instance as formatters may be stateful.
- */
+ // 24-Feb-2012, tatu: At this point, all timezone configuration should have
+ // occurred, with respect to default date format and time zone configuration.
+ // But we still better clone an instance as formatters may be stateful.
DateFormat df = _config.getDateFormat();
_dateFormat = df = (DateFormat) df.clone();
return df;
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
index cc05d78390..301117814b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
@@ -20,9 +20,9 @@
public enum DeserializationFeature implements ConfigFeature
{
/*
- /******************************************************
- /* Value (mostly scalar) conversion features
- /******************************************************
+ /**********************************************************************
+ /* Value (mostly scalar) mapping features
+ /**********************************************************************
*/
/**
@@ -83,8 +83,6 @@ public enum DeserializationFeature implements ConfigFeature
* Feature is disabled by default, meaning that "untyped" integral
* numbers will by default be deserialized using {@link java.lang.Integer}
* if value fits.
- *
- * @since 2.6
*/
USE_LONG_FOR_INTS(false),
@@ -100,9 +98,9 @@ public enum DeserializationFeature implements ConfigFeature
USE_JAVA_ARRAY_FOR_JSON_ARRAY(false),
/*
- /******************************************************
+ /**********************************************************************
/* Error handling features
- /******************************************************
+ /**********************************************************************
*/
/**
@@ -154,8 +152,6 @@ public enum DeserializationFeature implements ConfigFeature
*
* Feature is enabled by default so that exception is thrown for missing or invalid
* type information.
- *
- * @since 2.2
*/
FAIL_ON_INVALID_SUBTYPE(true),
@@ -171,8 +167,6 @@ public enum DeserializationFeature implements ConfigFeature
* keys. New features may be added to control additional cases.
*
* Feature is disabled by default so that no exception is thrown.
- *
- * @since 2.3
*/
FAIL_ON_READING_DUP_TREE_KEY(false),
@@ -182,8 +176,6 @@ public enum DeserializationFeature implements ConfigFeature
* {@link JsonMappingException} is thrown; if false, property is quietly skipped.
*
* Feature is disabled by default so that no exception is thrown.
- *
- * @since 2.3
*/
FAIL_ON_IGNORED_PROPERTIES(false),
@@ -198,8 +190,6 @@ public enum DeserializationFeature implements ConfigFeature
*
* Feature is enabled by default, so that unknown Object Ids will result in an
* exception being thrown, at the end of deserialization.
- *
- * @since 2.5
*/
FAIL_ON_UNRESOLVED_OBJECT_IDS(true),
@@ -219,8 +209,6 @@ public enum DeserializationFeature implements ConfigFeature
*
* Feature is disabled by default, so that no exception is thrown for missing creator
* property values, unless they are explicitly marked as `required`.
- *
- * @since 2.6
*/
FAIL_ON_MISSING_CREATOR_PROPERTIES(false),
@@ -232,8 +220,6 @@ public enum DeserializationFeature implements ConfigFeature
* if you are using Java or Scala optionals for non-mandatory fields.
* Feature is disabled by default, so that no exception is thrown for missing creator
* property values, unless they are explicitly marked as `required`.
- *
- * @since 2.8
*/
FAIL_ON_NULL_CREATOR_PROPERTIES(false),
@@ -246,8 +232,6 @@ public enum DeserializationFeature implements ConfigFeature
*
* Feature is enabled by default, so that exception is thrown when a subtype property is
* missing.
- *
- * @since 2.9
*/
FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY(true),
@@ -266,8 +250,6 @@ public enum DeserializationFeature implements ConfigFeature
*
* Feature is disabled by default (so that no check is made for possible trailing
* token(s)) for backwards compatibility reasons.
- *
- * @since 2.9
*/
FAIL_ON_TRAILING_TOKENS(false),
@@ -289,9 +271,9 @@ public enum DeserializationFeature implements ConfigFeature
WRAP_EXCEPTIONS(true),
/*
- /******************************************************
+ /**********************************************************************
/* Structural conversion features
- /******************************************************
+ /**********************************************************************
*/
/**
@@ -314,7 +296,6 @@ public enum DeserializationFeature implements ConfigFeature
*
*
* Feature is disabled by default
- * @since 2.4
*/
UNWRAP_SINGLE_VALUE_ARRAYS(false),
@@ -331,10 +312,32 @@ public enum DeserializationFeature implements ConfigFeature
UNWRAP_ROOT_VALUE(false),
/*
- /******************************************************
- /* Value conversion features
- /******************************************************
+ /**********************************************************************
+ /* Value conversion/coercion features
+ /**********************************************************************
*/
+
+ /**
+ * Feature that determines whether coercions from secondary representations are allowed
+ * for simple non-textual scalar types: numbers and booleans. This includes `primitive`
+ * types and their wrappers, but excludes `java.lang.String` and date/time types.
+ *
+ * When feature is disabled, only strictly compatible input may be bound: numbers for
+ * numbers, boolean values for booleans. When feature is enabled, conversions from
+ * JSON String are allowed, as long as textual value matches (for example, String
+ * "true" is allowed as equivalent of JSON boolean token `true`; or String "1.0"
+ * for `double`).
+ *
+ * Note that it is possible that other configurability options can override this
+ * in closer scope (like on per-type or per-property basis); this is just the global
+ * default.
+ *
+ * Feature is enabled by default (for backwards compatibility since this was the
+ * default behavior)
+ *
+ * @since 3.0 (in 2.x was a `MapperFeature` instead)
+ */
+ ALLOW_COERCION_OF_SCALARS(true),
/**
* Feature that can be enabled to allow JSON empty String
@@ -348,7 +351,7 @@ public enum DeserializationFeature implements ConfigFeature
*
* NOTE: this does NOT apply to scalar values such as booleans and numbers;
* whether they can be coerced depends on
- * {@link MapperFeature#ALLOW_COERCION_OF_SCALARS}.
+ * {@link #ALLOW_COERCION_OF_SCALARS}.
*
* Feature is disabled by default.
*/
@@ -365,8 +368,6 @@ public enum DeserializationFeature implements ConfigFeature
* to be equivalent of JSON null.
*
* Feature is disabled by default.
- *
- * @since 2.5
*/
ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false),
@@ -379,8 +380,6 @@ public enum DeserializationFeature implements ConfigFeature
* will be thrown.
*
* Feature is enabled by default.
- *
- * @since 2.6
*/
ACCEPT_FLOAT_AS_INT(true),
@@ -407,8 +406,6 @@ public enum DeserializationFeature implements ConfigFeature
* cases).
*
* Feature is disabled by default.
- *
- * @since 2.0
*/
READ_UNKNOWN_ENUM_VALUES_AS_NULL(false),
@@ -419,8 +416,6 @@ public enum DeserializationFeature implements ConfigFeature
* If enabled, but no predefined default Enum value is specified, an exception will be thrown as well.
*
* Feature is disabled by default.
- *
- * @since 2.8
*/
READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE(false),
@@ -436,8 +431,6 @@ public enum DeserializationFeature implements ConfigFeature
* This is the counterpart to {@link SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS}.
*
* Feature is enabled by default, to support most accurate time values possible.
- *
- * @since 2.2
*/
READ_DATE_TIMESTAMPS_AS_NANOSECONDS(true),
@@ -460,15 +453,13 @@ public enum DeserializationFeature implements ConfigFeature
*
* Taking above into account, this feature is supported only by extension modules for
* Joda and Java 8 date/tyime datatypes.
- *
- * @since 2.2
*/
ADJUST_DATES_TO_CONTEXT_TIME_ZONE(true),
/*
- /******************************************************
+ /**********************************************************************
/* Other
- /******************************************************
+ /**********************************************************************
*/
/**
@@ -482,8 +473,6 @@ public enum DeserializationFeature implements ConfigFeature
* feature: only consider that if there are actual perceived problems.
*
* Feature is enabled by default.
- *
- * @since 2.1
*/
EAGER_DESERIALIZER_FETCH(true)
diff --git a/src/main/java/com/fasterxml/jackson/databind/InjectableValues.java b/src/main/java/com/fasterxml/jackson/databind/InjectableValues.java
index 9f773c3ab8..4469aaa587 100644
--- a/src/main/java/com/fasterxml/jackson/databind/InjectableValues.java
+++ b/src/main/java/com/fasterxml/jackson/databind/InjectableValues.java
@@ -2,6 +2,8 @@
import java.util.*;
+import com.fasterxml.jackson.core.util.Snapshottable;
+
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
@@ -9,6 +11,7 @@
* "inject" during deserialization. An instance of this object
*/
public abstract class InjectableValues
+ implements Snapshottable
{
/**
* Method called to find value identified by id valueId
to
@@ -46,7 +49,7 @@ public static class Std
protected final Map _values;
public Std() {
- this(new HashMap());
+ this(new HashMap<>());
}
public Std(Map values) {
@@ -62,7 +65,15 @@ public Std addValue(Class> classKey, Object value) {
_values.put(classKey.getName(), value);
return this;
}
-
+
+ @Override
+ public Std snapshot() {
+ if (_values.isEmpty()) {
+ return new Std();
+ }
+ return new Std(new HashMap<>(_values));
+ }
+
@Override
public Object findInjectableValue(Object valueId, DeserializationContext ctxt,
BeanProperty forProperty, Object beanInstance) throws JsonMappingException
diff --git a/src/main/java/com/fasterxml/jackson/databind/JavaType.java b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
index 3fdbb2b1f2..ae1227ed9d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JavaType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
@@ -13,14 +13,11 @@
*
* Instances can (only) be constructed by
* com.fasterxml.jackson.databind.type.TypeFactory
.
- *
- * Since 2.2 this implements {@link java.lang.reflect.Type} to allow
- * it to be pushed through interfaces that only expose that type.
*/
public abstract class JavaType
extends ResolvedType
- implements java.io.Serializable, // 2.1
- java.lang.reflect.Type // 2.2
+ implements java.io.Serializable,
+ java.lang.reflect.Type
{
private static final long serialVersionUID = 1;
@@ -57,8 +54,6 @@ public abstract class JavaType
/**
* Whether entities defined with this type should be handled using
* static typing (as opposed to dynamic runtime type) or not.
- *
- * @since 2.2
*/
protected final boolean _asStatic;
@@ -85,8 +80,6 @@ protected JavaType(Class> raw, int additionalHash,
/**
* Copy-constructor used when refining/upgrading type instances.
- *
- * @since 2.7
*/
protected JavaType(JavaType base)
{
@@ -134,8 +127,6 @@ protected JavaType(JavaType base)
* Mutant factory method that will try to copy handlers that the specified
* source type instance had, if any; this must be done recursively where
* necessary (as content types may be structured).
- *
- * @since 2.8.4
*/
public JavaType withHandlersFrom(JavaType src) {
JavaType type = this;
@@ -162,8 +153,6 @@ public JavaType withHandlersFrom(JavaType src) {
* will be thrown.
*
* @return Newly created type instance
- *
- * @since 2.7
*/
public abstract JavaType withContentType(JavaType contentType);
@@ -175,8 +164,6 @@ public JavaType withHandlersFrom(JavaType src) {
* The main use case is to allow forcing of specific root value serialization type,
* and specifically in resolving serializers for contained types (element types
* for arrays, Collections and Maps).
- *
- * @since 2.2
*/
public abstract JavaType withStaticTyping();
@@ -191,31 +178,9 @@ public JavaType withHandlersFrom(JavaType src) {
* for known parameterized types; for other types will return `null` to indicate
* that no just refinement makes necessary sense, without trying to detect
* special status through implemented interfaces.
- *
- * @since 2.7
*/
public abstract JavaType refine(Class> rawType, TypeBindings bindings,
JavaType superClass, JavaType[] superInterfaces);
-
- /**
- * Legacy method used for forcing sub-typing of this type into
- * type specified by specific type erasure.
- * Deprecated as of 2.7 as such specializations really ought to
- * go through {@link TypeFactory}, not directly via {@link JavaType}.
- *
- * @since 2.7
- */
- @Deprecated
- public JavaType forcedNarrowBy(Class> subclass)
- {
- if (subclass == _class) { // can still optimize for simple case
- return this;
- }
- return _narrow(subclass);
- }
-
- @Deprecated // since 2.7
- protected abstract JavaType _narrow(Class> subclass);
/*
/**********************************************************
@@ -238,23 +203,15 @@ public JavaType forcedNarrowBy(Class> subclass)
* Accessor that allows determining whether {@link #getContentType()} should
* return a non-null value (that is, there is a "content type") or not.
* True if {@link #isContainerType()} or {@link #isReferenceType()} return true.
- *
- * @since 2.8
*/
public boolean hasContentType() {
return true;
}
- /**
- * @since 2.6
- */
public final boolean isTypeOrSubTypeOf(Class> clz) {
return (_class == clz) || clz.isAssignableFrom(_class);
}
- /**
- * @since 2.9
- */
public final boolean isTypeOrSuperTypeOf(Class> clz) {
return (_class == clz) || _class.isAssignableFrom(clz);
}
@@ -328,8 +285,6 @@ public boolean isConcrete() {
* getRawClass() == Object.class
*
* and used to figure if we basically have "untyped" type object.
- *
- * @since 2.5
*/
public final boolean isJavaLangObject() { return _class == Object.class; }
@@ -338,8 +293,6 @@ public boolean isConcrete() {
* this type should use static typing (as opposed to dynamic typing).
* Note that while value of 'true' does mean that static typing is to
* be used, value of 'false' may still be overridden by other settings.
- *
- * @since 2.2
*/
public final boolean useStaticType() { return _asStatic; }
@@ -358,7 +311,7 @@ public boolean isConcrete() {
@Override
public JavaType getContentType() { return null; }
- @Override // since 2.6
+ @Override
public JavaType getReferencedType() { return null; }
@Override
@@ -366,16 +319,6 @@ public boolean isConcrete() {
@Override
public abstract JavaType containedType(int index);
-
- @Deprecated // since 2.7
- @Override
- public abstract String containedTypeName(int index);
-
- @Deprecated // since 2.7
- @Override
- public Class> getParameterSource() {
- return null;
- }
/*
/**********************************************************
@@ -396,17 +339,12 @@ public Class> getParameterSource() {
* where we just want to check if containedType is available first; and
* if not, use "unknown type" (which translates to java.lang.Object
* basically).
- *
- * @since 2.5
*/
public JavaType containedTypeOrUnknown(int index) {
JavaType t = containedType(index);
return (t == null) ? TypeFactory.unknownType() : t;
}
- /**
- * @since 2.7
- */
public abstract TypeBindings getBindings();
/**
@@ -415,32 +353,24 @@ public JavaType containedTypeOrUnknown(int index) {
* type has given erased type), one of its supertypes that has the
* erased types, or null if target is neither this type or any of its
* supertypes.
- *
- * @since 2.7
*/
public abstract JavaType findSuperType(Class> erasedTarget);
/**
* Accessor for finding fully resolved parent class of this type,
* if it has one; null if not.
- *
- * @since 2.7
*/
public abstract JavaType getSuperClass();
/**
* Accessor for finding fully resolved interfaces this type implements,
* if any; empty array if none.
- *
- * @since 2.7
*/
public abstract List getInterfaces();
/**
* Method that may be used to find paramaterization this type has for
* given type-erased generic target type.
- *
- * @since 2.7
*/
public abstract JavaType[] findTypeParameters(Class> expType);
@@ -462,19 +392,11 @@ public JavaType containedTypeOrUnknown(int index) {
@SuppressWarnings("unchecked")
public T getTypeHandler() { return (T) _typeHandler; }
- /**
- * @since 2.7
- */
public Object getContentValueHandler() { return null; }
- /**
- * @since 2.7
- */
public Object getContentTypeHandler() { return null; }
- /**
- * @since 2.6
- */
+
public boolean hasValueHandler() { return _valueHandler != null; }
/**
@@ -482,8 +404,6 @@ public JavaType containedTypeOrUnknown(int index) {
* or content type has {@link #getValueHandler} or {@link #getTypeHandler()};
* that is, are there any non-standard handlers associated with this
* type object.
- *
- * @since 2.8
*/
public boolean hasHandlers() {
return (_typeHandler != null) || (_valueHandler != null);
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
index 469055f174..a7b46dabe2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
@@ -22,7 +22,7 @@
*
* If deserializer is an aggregate one -- meaning it delegates handling of some
* of its contents by using other deserializer(s) -- it typically also needs
- * to implement {@link com.fasterxml.jackson.databind.deser.ResolvableDeserializer},
+ * to implement {@link #resolve}
* which can locate dependant deserializers. This is important to allow dynamic
* overrides of deserializers; separate call interface is needed to separate
* resolution of dependant deserializers (which may have cyclic link back
@@ -30,26 +30,66 @@
*
* In addition, to support per-property annotations (to configure aspects
* of deserialization on per-property basis), deserializers may want
- * to implement
- * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer},
- * which allows specialization of deserializers: call to
- * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer#createContextual}
- * is passed information on property, and can create a newly configured
+ * to override
+ * {@link #createContextual} which allows specialization of deserializers:
+ * it is passed information on property, and can create a newly configured
* deserializer for handling that particular property.
- *
- * If both
- * {@link com.fasterxml.jackson.databind.deser.ResolvableDeserializer} and
- * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer}
- * are implemented, resolution of deserializers occurs before
- * contextualization.
+ *
+ * Resolution of deserializers occurs before contextualization.
*/
public abstract class JsonDeserializer
- implements NullValueProvider // since 2.9
+ implements NullValueProvider
{
/*
- /**********************************************************
+ /**********************************************************************
+ /* Initialization, with former `ResolvableDeserializer`, `ContextualDeserializer`
+ /**********************************************************************
+ */
+
+ /**
+ * Method called after deserializer instance has been constructed
+ * (and registered as necessary by provider objects),
+ * but before it has returned it to the caller.
+ * Called object can then resolve its dependencies to other types,
+ * including self-references (direct or indirect).
+ *
+ * @param ctxt Context to use for accessing configuration, resolving
+ * secondary deserializers
+ */
+ public void resolve(DeserializationContext ctxt) throws JsonMappingException {
+ // Default implementation does nothing
+ }
+
+ /**
+ * Method called to see if a different (or differently configured) deserializer
+ * is needed to deserialize values of specified property.
+ * Note that instance that this method is called on is typically shared one and
+ * as a result method should NOT modify this instance but rather construct
+ * and return a new instance. This instance should only be returned as-is, in case
+ * it is already suitable for use.
+ *
+ * @param ctxt Deserialization context to access configuration, additional
+ * deserializers that may be needed by this deserializer
+ * @param property Method, field or constructor parameter that represents the property
+ * (and is used to assign deserialized value).
+ * Should be available; but there may be cases where caller cannot provide it and
+ * null is passed instead (in which case impls usually pass 'this' deserializer as is)
+ *
+ * @return Deserializer to use for deserializing values of specified property;
+ * may be this instance or a new instance.
+ *
+ * @throws JsonMappingException
+ */
+ public JsonDeserializer> createContextual(DeserializationContext ctxt,
+ BeanProperty property) throws JsonMappingException {
+ // default implementation returns instance unmodified
+ return this;
+ }
+
+ /*
+ /**********************************************************************
/* Main deserialization methods
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -155,9 +195,9 @@ public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
}
/*
- /**********************************************************
+ /**********************************************************************
/* Fluent factory methods for constructing decorated versions
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -169,7 +209,8 @@ public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
* Default implementation just returns 'this'
* indicating that no unwrapped variant exists
*/
- public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) {
+ public JsonDeserializer unwrappingDeserializer(DeserializationContext ctxt,
+ NameTransformer unwrapper) {
return this;
}
@@ -179,18 +220,16 @@ public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) {
* delegate anything; or it does not want any changes), should either
* throw {@link UnsupportedOperationException} (if operation does not
* make sense or is not allowed); or return this deserializer as is.
- *
- * @since 2.1
*/
public JsonDeserializer> replaceDelegatee(JsonDeserializer> delegatee) {
throw new UnsupportedOperationException();
}
/*
- /**********************************************************
+ /**********************************************************************
/* Introspection methods for figuring out configuration/setup
/* of this deserializer instance and/or type it handles
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -202,8 +241,6 @@ public JsonDeserializer> replaceDelegatee(JsonDeserializer> delegatee) {
* Default implementation will return null, which means almost same
* same as returning Object.class
would; that is, that
* nothing is known about handled type.
- *
- * @since 2.3
*/
public Class> handledType() { return null; }
@@ -212,14 +249,14 @@ public JsonDeserializer> replaceDelegatee(JsonDeserializer> delegatee) {
* usable for other properties of same type (type for which instance
* was created).
*
- * Note that cached instances are still resolved on per-property basis,
- * if instance implements {@link com.fasterxml.jackson.databind.deser.ResolvableDeserializer}:
- * cached instance is just as the base. This means that in most cases it is safe to
+ * Note that cached instances are still contextualized on per-property basis
+ * (but note that {@link JsonDeserializer#resolve(DeserializationContext)}d
+ * just once!)
+ * This means that in most cases it is safe to
* cache instances; however, it only makes sense to cache instances
* if instantiation is expensive, or if instances are heavy-weight.
*
- * Default implementation returns false, to indicate that no caching
- * is done.
+ * Default implementation returns false, to indicate that no caching is done.
*/
public boolean isCachable() { return false; }
@@ -231,8 +268,6 @@ public JsonDeserializer> replaceDelegatee(JsonDeserializer> delegatee) {
*
* @return Deserializer this deserializer delegates calls to, if null;
* null otherwise.
- *
- * @since 2.1
*/
public JsonDeserializer> getDelegatee() {
return null;
@@ -247,17 +282,15 @@ public JsonDeserializer> getDelegatee() {
* This is only to be used for error reporting and diagnostics
* purposes (most commonly, to accompany "unknown property"
* exception).
- *
- * @since 2.0
*/
public Collection getKnownPropertyNames() {
return null;
}
/*
- /**********************************************************
+ /**********************************************************************
/* Default NullValueProvider implementation
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -267,18 +300,14 @@ public Collection getKnownPropertyNames() {
* Java null, but for some types (especially primitives) it may be
* necessary to use non-null values.
*
- * Since version 2.6 (in which the context argument was added), call is
- * expected to be made each and every time a null token needs to
- * be handled.
+ * Call is expected to be made each and every time a null token
+ * needs to be handled.
*
* Default implementation simply returns null.
- *
- * @since 2.6 Added to replace earlier no-arguments variant
*/
@Override
public T getNullValue(DeserializationContext ctxt) throws JsonMappingException {
- // Change the direction in 2.7
- return getNullValue();
+ return null;
}
/**
@@ -299,17 +328,15 @@ public AccessPattern getNullAccessPattern() {
* {@link #getEmptyValue(DeserializationContext)}, to check whether it needs
* to be called just once (static values), or each time empty value is
* needed.
- *
- * @since 2.9
*/
public AccessPattern getEmptyAccessPattern() {
return AccessPattern.DYNAMIC;
}
/*
- /**********************************************************
+ /**********************************************************************
/* Other accessors
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -327,8 +354,6 @@ public AccessPattern getEmptyAccessPattern() {
*
* Default implementation simply calls {@link #getNullValue} and
* returns value.
- *
- * @since 2.6 Added to replace earlier no-arguments variant
*/
public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
return getNullValue(ctxt);
@@ -349,16 +374,12 @@ public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingExcep
* @return ObjectIdReader used for resolving possible Object Identifier
* value, instead of full value serialization, if deserializer can do that;
* null if no Object Id is expected.
- *
- * @since 2.0
*/
- public ObjectIdReader getObjectIdReader() { return null; }
+ public ObjectIdReader getObjectIdReader(DeserializationContext ctxt) { return null; }
/**
* Method needed by {@link BeanDeserializerFactory} to properly link
* managed- and back-reference pairs.
- *
- * @since 2.2 (was moved out of BeanDeserializerBase
)
*/
public SettableBeanProperty findBackReference(String refName)
{
@@ -382,35 +403,15 @@ public SettableBeanProperty findBackReference(String refName)
*
* Default implementation returns null
to allow explicit per-type
* or per-property attempts.
- *
- * @since 2.9
*/
public Boolean supportsUpdate(DeserializationConfig config) {
return null;
}
/*
- /**********************************************************
- /* Deprecated methods
- /**********************************************************
- */
-
- /**
- * @deprecated Since 2.6 Use overloaded variant that takes context argument
- */
- @Deprecated
- public T getNullValue() { return null; }
-
- /**
- * @deprecated Since 2.6 Use overloaded variant that takes context argument
- */
- @Deprecated
- public Object getEmptyValue() { return getNullValue(); }
-
- /*
- /**********************************************************
+ /**********************************************************************
/* Helper classes
- /**********************************************************
+ /**********************************************************************
*/
/**
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java b/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
index 4c258186f4..f12dba460b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
@@ -207,33 +207,6 @@ Object writeReplace() {
/**********************************************************
*/
- /**
- * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead
- */
- @Deprecated // since 2.7
- public JsonMappingException(String msg) { super(msg); }
-
- /**
- * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead
- */
- @Deprecated // since 2.7
- public JsonMappingException(String msg, Throwable rootCause) { super(msg, rootCause); }
-
- /**
- * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead
- */
- @Deprecated // since 2.7
- public JsonMappingException(String msg, JsonLocation loc) { super(msg, loc); }
-
- /**
- * @deprecated Since 2.7 Use variant that takes {@link JsonParser} instead
- */
- @Deprecated // since 2.7
- public JsonMappingException(String msg, JsonLocation loc, Throwable rootCause) { super(msg, loc, rootCause); }
-
- /**
- * @since 2.7
- */
public JsonMappingException(Closeable processor, String msg) {
super(msg);
_processor = processor;
@@ -245,9 +218,6 @@ public JsonMappingException(Closeable processor, String msg) {
}
}
- /**
- * @since 2.7
- */
public JsonMappingException(Closeable processor, String msg, Throwable problem) {
super(msg, problem);
_processor = processor;
@@ -256,73 +226,46 @@ public JsonMappingException(Closeable processor, String msg, Throwable problem)
}
}
- /**
- * @since 2.7
- */
public JsonMappingException(Closeable processor, String msg, JsonLocation loc) {
super(msg, loc);
_processor = processor;
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(JsonParser p, String msg) {
return new JsonMappingException(p, msg);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(JsonParser p, String msg, Throwable problem) {
return new JsonMappingException(p, msg, problem);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(JsonGenerator g, String msg) {
return new JsonMappingException(g, msg, (Throwable) null);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(JsonGenerator g, String msg, Throwable problem) {
return new JsonMappingException(g, msg, problem);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(DeserializationContext ctxt, String msg) {
return new JsonMappingException(ctxt.getParser(), msg);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(DeserializationContext ctxt, String msg, Throwable t) {
return new JsonMappingException(ctxt.getParser(), msg, t);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(SerializerProvider ctxt, String msg) {
return new JsonMappingException(ctxt.getGenerator(), msg);
}
- /**
- * @since 2.7
- */
public static JsonMappingException from(SerializerProvider ctxt, String msg, Throwable problem) {
/* 17-Aug-2015, tatu: As per [databind#903] this is bit problematic as
* SerializerProvider instance does not currently hold on to generator...
*/
return new JsonMappingException(ctxt.getGenerator(), msg, problem);
}
-
+
/**
* Factory method used when "upgrading" an {@link IOException} into
* {@link JsonMappingException}: usually only needed to comply with
@@ -330,8 +273,6 @@ public static JsonMappingException from(SerializerProvider ctxt, String msg, Thr
*
* NOTE: since 2.9 should usually NOT be used on input-side (deserialization)
* exceptions; instead use method(s) of InputMismatchException
- *
- * @since 2.1
*/
public static JsonMappingException fromUnexpectedIOE(IOException src) {
return new JsonMappingException(null,
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonNode.java b/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
index d8c226604f..e41003f0c7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
@@ -30,7 +30,7 @@
* {@link com.fasterxml.jackson.databind.node}.
*
* Note that it is possible to "read" from nodes, using
- * method {@link TreeNode#traverse(ObjectCodec)}, which will result in
+ * method {@link TreeNode#traverse}, which will result in
* a {@link JsonParser} being constructed. This can be used for (relatively)
* efficient conversations between different representations; and it is what
* core databind uses for methods like {@link ObjectMapper#treeToValue(TreeNode, Class)}
@@ -41,9 +41,9 @@ public abstract class JsonNode
implements TreeNode, Iterable
{
/*
- /**********************************************************
+ /**********************************************************************
/* Construction, related
- /**********************************************************
+ /**********************************************************************
*/
protected JsonNode() { }
@@ -59,18 +59,16 @@ protected JsonNode() { }
* Note: return type is guaranteed to have same type as the
* node method is called on; which is why method is declared
* with local generic type.
- *
- * @since 2.0
- *
+ *
* @return Node that is either a copy of this node (and all non-leaf
* children); or, for immutable leaf nodes, node itself.
*/
public abstract T deepCopy();
/*
- /**********************************************************
+ /**********************************************************************
/* TreeNode implementation
- /**********************************************************
+ /**********************************************************************
*/
// public abstract JsonToken asToken();
@@ -201,8 +199,6 @@ public Iterator fieldNames() {
*
* @return Node that matches given JSON Pointer: if no match exists,
* will return a node for which {@link #isMissingNode()} returns true.
- *
- * @since 2.3
*/
@Override
public final JsonNode at(JsonPointer ptr)
@@ -233,8 +229,6 @@ public final JsonNode at(JsonPointer ptr)
*
* @return Node that matches given JSON Pointer: if no match exists,
* will return a node for which {@link TreeNode#isMissingNode()} returns true.
- *
- * @since 2.3
*/
@Override
public final JsonNode at(String jsonPtrExpr) {
@@ -244,9 +238,9 @@ public final JsonNode at(String jsonPtrExpr) {
protected abstract JsonNode _at(JsonPointer ptr);
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, type introspection
- /**********************************************************
+ /**********************************************************************
*/
// // First high-level division between values, containers and "missing"
@@ -255,8 +249,6 @@ public final JsonNode at(String jsonPtrExpr) {
* Return the type of this node
*
* @return the node type as a {@link JsonNodeType} enum value
- *
- * @since 2.2
*/
public abstract JsonNodeType getNodeType();
@@ -328,9 +320,6 @@ public final boolean isNumber() {
*/
public boolean isLong() { return false; }
- /**
- * @since 2.2
- */
public boolean isFloat() { return false; }
public boolean isDouble() { return false; }
@@ -384,8 +373,6 @@ public final boolean isBinary() {
* from JSON String into Number; so even if this method returns false,
* it is possible that {@link #asInt} could still succeed
* if node is a JSON String representing integral number, or boolean.
- *
- * @since 2.0
*/
public boolean canConvertToInt() { return false; }
@@ -400,15 +387,13 @@ public final boolean isBinary() {
* from JSON String into Number; so even if this method returns false,
* it is possible that {@link #asLong} could still succeed
* if node is a JSON String representing integral number, or boolean.
- *
- * @since 2.0
*/
public boolean canConvertToLong() { return false; }
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, straight value access
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -501,8 +486,6 @@ public byte[] binaryValue() throws IOException {
* that an overflow is possible for `long` values
*
* @return 32-bit float value this node contains, if any; 0.0 for non-number nodes.
- *
- * @since 2.2
*/
public float floatValue() { return 0.0f; }
@@ -514,8 +497,6 @@ public byte[] binaryValue() throws IOException {
* in overflows with {@link BigInteger} values.
*
* @return 64-bit double value this node contains, if any; 0.0 for non-number nodes.
- *
- * @since 2.2
*/
public double doubleValue() { return 0.0; }
@@ -529,7 +510,7 @@ public byte[] binaryValue() throws IOException {
public BigDecimal decimalValue() { return BigDecimal.ZERO; }
/**
- * Returns integer value for this node (as {@link BigDecimal}), if and only if
+ * Returns integer value for this node (as {@link BigInteger}), if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns BigInteger.ZERO
.
*
@@ -538,9 +519,9 @@ public byte[] binaryValue() throws IOException {
public BigInteger bigIntegerValue() { return BigInteger.ZERO; }
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, value access with conversion(s)/coercion(s)
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -556,8 +537,6 @@ public byte[] binaryValue() throws IOException {
* defaultValue
in cases where null value would be returned;
* either for missing nodes (trying to access missing property, or element
* at invalid item for array) or explicit nulls.
- *
- * @since 2.4
*/
public String asText(String defaultValue) {
String str = asText();
@@ -567,8 +546,8 @@ public String asText(String defaultValue) {
/**
* Method that will try to convert value of this node to a Java int .
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
- * and 1 (true), and Strings are parsed using default Java language integer
- * parsing rules.
+ * and 1 (true), and Strings are parsed using
+ * {@link com.fasterxml.jackson.core.io.NumberInput#parseAsInt(String, int)}
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
@@ -581,8 +560,8 @@ public int asInt() {
/**
* Method that will try to convert value of this node to a Java int .
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
- * and 1 (true), and Strings are parsed using default Java language integer
- * parsing rules.
+ * and 1 (true), and Strings are parsed using
+ * {@link com.fasterxml.jackson.core.io.NumberInput#parseAsInt(String, int)}
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
@@ -595,8 +574,8 @@ public int asInt(int defaultValue) {
/**
* Method that will try to convert value of this node to a Java long .
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
- * and 1 (true), and Strings are parsed using default Java language integer
- * parsing rules.
+ * and 1 (true), and Strings are parsed using
+ * {@link com.fasterxml.jackson.core.io.NumberInput#parseAsLong(String, long)}
*
* If representation cannot be converted to an long (including structured types
* like Objects and Arrays),
@@ -609,8 +588,8 @@ public long asLong() {
/**
* Method that will try to convert value of this node to a Java long .
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
- * and 1 (true), and Strings are parsed using default Java language integer
- * parsing rules.
+ * and 1 (true), and Strings are parsed using
+ * {@link com.fasterxml.jackson.core.io.NumberInput#parseAsLong(String, long)}
*
* If representation cannot be converted to an long (including structured types
* like Objects and Arrays),
@@ -623,8 +602,8 @@ public long asLong(long defaultValue) {
/**
* Method that will try to convert value of this node to a Java double .
* Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
- * and 1.0 (true), and Strings are parsed using default Java language integer
- * parsing rules.
+ * and 1.0 (true), and Strings are parsed using
+ * {@link com.fasterxml.jackson.core.io.NumberInput#parseAsDouble(String, double)}
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
@@ -637,8 +616,8 @@ public double asDouble() {
/**
* Method that will try to convert value of this node to a Java double .
* Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
- * and 1.0 (true), and Strings are parsed using default Java language integer
- * parsing rules.
+ * and 1.0 (true), and Strings are parsed using
+ * {@link com.fasterxml.jackson.core.io.NumberInput#parseAsDouble(String, double)}
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
@@ -677,9 +656,9 @@ public boolean asBoolean(boolean defaultValue) {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, value find / existence check methods
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -740,8 +719,6 @@ public boolean has(int index) {
*
* node.get(fieldName) != null && !node.get(fieldName).isNull()
*
- *
- * @since 2.1
*/
public boolean hasNonNull(String fieldName) {
JsonNode n = get(fieldName);
@@ -756,8 +733,6 @@ public boolean hasNonNull(String fieldName) {
*
* node.get(index) != null && !node.get(index).isNull()
*
- *
- * @since 2.1
*/
public boolean hasNonNull(int index) {
JsonNode n = get(index);
@@ -765,9 +740,9 @@ public boolean hasNonNull(int index) {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, container access
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -797,9 +772,9 @@ public Iterator> fields() {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, find methods
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -892,9 +867,9 @@ public final List findParents(String fieldName)
public abstract List findParents(String fieldName, List foundSoFar);
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, path handling
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -924,9 +899,9 @@ public JsonNode withArray(String propertyName) {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Public API, comparison
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -944,21 +919,19 @@ public JsonNode withArray(String propertyName) {
*
* @param comparator Object called to compare two scalar {@link JsonNode}
* instances, and return either 0 (are equals) or non-zero (not equal)
- *
- * @since 2.6
*/
public boolean equals(Comparator comparator, JsonNode other) {
return comparator.compare(this, other) == 0;
}
/*
- /**********************************************************
+ /**********************************************************************
/* Overridden standard methods
- /**********************************************************
+ /**********************************************************************
*/
/**
- * Method that will produce (as of Jackson 2.10) valid JSON using
+ * Method that will produce valid JSON using
* default settings of databind, as String.
* If you want other kinds of JSON output (or output formatted using one of
* other Jackson-supported data formats) make sure to use
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonSerializable.java b/src/main/java/com/fasterxml/jackson/databind/JsonSerializable.java
index a08898a74c..f3b4419a57 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonSerializable.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonSerializable.java
@@ -48,8 +48,6 @@ public void serializeWithType(JsonGenerator gen, SerializerProvider serializers,
* that core Jackson databinding makes use of.
* Use of this base class is strongly recommended over directly implementing
* {@link JsonSerializable}.
- *
- * @since 2.6
*/
public abstract static class Base implements JsonSerializable
{
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java b/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
index 11c01b24a4..390bdf25f5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonSerializer.java
@@ -3,6 +3,7 @@
import java.io.IOException;
import java.util.Iterator;
+import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
@@ -16,47 +17,98 @@
* Abstract class that defines API used by {@link ObjectMapper} (and
* other chained {@link JsonSerializer}s too) to serialize Objects of
* arbitrary types into JSON, using provided {@link JsonGenerator}.
- * {@link com.fasterxml.jackson.databind.ser.std.StdSerializer} instead
- * of this class, since it will implement many of optional
- * methods of this class.
- *
- * NOTE: various serialize
methods are never (to be) called
- * with null values -- caller must handle null values, usually
- * by calling {@link SerializerProvider#findNullValueSerializer} to obtain
- * serializer to use.
- * This also means that custom serializers cannot be directly used to change
- * the output to produce when serializing null values.
+ * Note that although API is defined here, custom serializer implementations
+ * should almost always be based on {@link com.fasterxml.jackson.databind.ser.std.StdSerializer}
+ * since it will implement many of optional methods of this class.
*
* If serializer is an aggregate one -- meaning it delegates handling of some
* of its contents by using other serializer(s) -- it typically also needs
- * to implement {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer},
- * which can locate secondary serializers needed. This is important to allow dynamic
+ * to implement {@link #resolve} which can locate secondary serializers needed.
+ * This is important to allow dynamic
* overrides of serializers; separate call interface is needed to separate
* resolution of secondary serializers (which may have cyclic link back
* to serializer itself, directly or indirectly).
*
- * In addition, to support per-property annotations (to configure aspects
- * of serialization on per-property basis), serializers may want
- * to implement
- * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer},
- * which allows specialization of serializers: call to
- * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer#createContextual}
- * is passed information on property, and can create a newly configured
- * serializer for handling that particular property.
+ * Initialization of serializers is handled by two main methods:
+ *
+ * {@link #resolve}: called after instance is configured to be used for specific type,
+ * but without yet knowing property it will be used for (or, in case of root values, without property).
+ * Method needs to be implemented for serializers that may work on cyclic types, and specifically
+ * is implemented by standard POJO serializer ({@code BeanSerializer}). It is usually not needed for
+ * container types as their type definitions are not cyclic, unlike some POJO types.
+ * {@link #createContextual}: called on resolved instance (whether newly created, or found via cache),
+ * when serializer is to be used for specific property, or as root value serializer (no referring property).
+ * It is used to apply annotations from property accessors (getter, field), and may also be used for resolving
+ * nested types for container serializers (such as ones for {@link java.util.Collection}s).
+ *
+ * Caching of serializers occurs after {@link #resolve} is called: cached instances are not contextual.
*
- * If both
- * {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer} and
- * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}
- * are implemented, resolution of serializers occurs before
- * contextualization.
+ * NOTE: various serialize
methods are never (to be) called
+ * with null values -- caller must handle null values, usually
+ * by calling {@link SerializerProvider#findNullValueSerializer} to obtain
+ * serializer to use.
+ * This also means that custom serializers cannot be directly used to change
+ * the output to produce when serializing null values.
*/
public abstract class JsonSerializer
- implements JsonFormatVisitable // since 2.1
+ implements JsonFormatVisitable
{
/*
- /**********************************************************
+ /**********************************************************************
+ /* Initialization, with former `ResolvableSerializer`,
+ /* `ContextualSerializer`.
+ /**********************************************************************
+ */
+
+ /**
+ * Method called after {@link SerializerProvider} has registered
+ * the serializer, but before it has returned it to the caller.
+ * Called object can then resolve its dependencies to other types,
+ * including self-references (direct or indirect).
+ *
+ * Note that this method does NOT return serializer, since resolution
+ * is not allowed to change actual serializer to use.
+ *
+ * @param provider Provider that has constructed serializer this method
+ * is called on.
+ */
+ public void resolve(SerializerProvider provider) throws JsonMappingException {
+ // Default implementation does nothing
+ }
+
+ /**
+ * Method called to see if a different (or differently configured) serializer
+ * is needed to serialize values of specified property (or, for root values, in which
+ * case `null` is passed).
+ * Note that instance that this method is called on is typically shared one and
+ * as a result method should NOT modify this instance but rather construct
+ * and return a new instance. This instance should only be returned as-is, in case
+ * it is already suitable for use.
+ *
+ * Note that method is only called once per POJO property, and for the first usage as root
+ * value serializer; it is not called for every serialization, as doing that would have
+ * significant performance impact; most serializers cache contextual instances for future
+ * use.
+ *
+ * @param prov Serializer provider to use for accessing config, other serializers
+ * @param property Property (defined by one or more accessors - field or method - used
+ * for accessing logical property value) for which serializer is used to be used;
+ * or, `null` for root value (or in cases where caller does not have this information,
+ * which is handled as root value case).
+ *
+ * @return Serializer to use for serializing values of specified property;
+ * may be this instance or a new instance.
+ */
+ public JsonSerializer> createContextual(SerializerProvider prov,
+ BeanProperty property) throws JsonMappingException {
+ // default implementation returns instance unmodified
+ return this;
+ }
+
+ /*
+ /**********************************************************************
/* Fluent factory methods for constructing decorated versions
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -83,8 +135,6 @@ public JsonSerializer unwrappingSerializer(NameTransformer unwrapper) {
* delegate anything; or it does not want any changes), should either
* throw {@link UnsupportedOperationException} (if operation does not
* make sense or is not allowed); or return this serializer as is.
- *
- * @since 2.1
*/
public JsonSerializer replaceDelegatee(JsonSerializer> delegatee) {
throw new UnsupportedOperationException();
@@ -97,17 +147,54 @@ public JsonSerializer replaceDelegatee(JsonSerializer> delegatee) {
*
* Default implementation simply returns this
; sub-classes that do support
* filtering will need to create and return new instance if filter changes.
- *
- * @since 2.6
*/
public JsonSerializer> withFilterId(Object filterId) {
return this;
}
+ /**
+ * Mutant factory called if there is need to create a serializer with specified
+ * format overrides (typically from property on which this serializer would be used,
+ * based on type declaration). Method is called before {@link #createContextual}
+ * but right after serializer is either constructed or fetched from cache.
+ *
+ * Method can do one of three things:
+ *
+ * Return {@code this} instance as is: this means that none of overrides has any effect
+ *
+ * Return an alternate {@link JsonSerializer}, suitable for use with specified format
+ *
+ * Return {@code null} to indicate that this serializer instance is not suitable for
+ * handling format variation, but does not know how to construct new serializer: caller
+ * will typically then call {@link com.fasterxml.jackson.databind.ser.SerializerFactory} with overrides to construct new serializer
+ *
+ *
+ * One example of second approach is the case where {@link com.fasterxml.jackson.annotation.JsonFormat.Shape#STRING} indicates String
+ * representation and code can just construct simple "string-like serializer", or variant of itself
+ * (similar to how {@link #createContextual} is often implemented).
+ * And third case (returning {@code null}) is applicable for cases like format defines
+ * {@link com.fasterxml.jackson.annotation.JsonFormat.Shape#POJO}, requesting "introspect serializer for POJO regardless of type":
+ * {@link com.fasterxml.jackson.databind.ser.SerializerFactory} is needed for full re-introspection, typically.
+ *
+ * @param formatOverrides (not null) Override settings, NOT including original format settings (which
+ * serializer needs to explicitly retain if needed)
+ *
+ * @since 3.0
+ */
+ public JsonSerializer> withFormatOverrides(SerializationConfig config,
+ JsonFormat.Value formatOverrides)
+ {
+ // First: if no override, safe to use as is:
+ if (formatOverrides.getShape() == JsonFormat.Shape.ANY) {
+ return this;
+ }
+ return null;
+ }
+
/*
- /**********************************************************
+ /**********************************************************************
/* Serialization methods
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -163,9 +250,9 @@ public void serializeWithType(T value, JsonGenerator gen, SerializerProvider ser
}
/*
- /**********************************************************
- /* Other accessors
- /**********************************************************
+ /**********************************************************************
+ /* Accessors for serializer metadata
+ /**********************************************************************
*/
/**
@@ -174,43 +261,10 @@ public void serializeWithType(T value, JsonGenerator gen, SerializerProvider ser
* may be a more generic (super-type) -- but it should not be
* incorrect (return a non-related type).
*
- * Default implementation will return null, which essentially means
- * same as returning Object.class
would; that is, that
- * nothing is known about handled type.
- *
+ * NOTE: starting with 3.0, left {@code abstract}.
*/
- public Class handledType() { return null; }
+ public Class> handledType() { return Object.class; }
- /**
- * Method called to check whether given serializable value is
- * considered "empty" value (for purposes of suppressing serialization
- * of empty values).
- *
- * Default implementation will consider only null values to be empty.
- *
- * @deprecated Since 2.5 Use {@link #isEmpty(SerializerProvider, Object)} instead;
- * will be removed from 3.0
- */
- @Deprecated
- public boolean isEmpty(T value) {
- return isEmpty(null, value);
- }
-
- /**
- * Method called to check whether given serializable value is
- * considered "empty" value (for purposes of suppressing serialization
- * of empty values).
- *
- * Default implementation will consider only null values to be empty.
- *
- * NOTE: replaces {@link #isEmpty(Object)}, which was deprecated in 2.5
- *
- * @since 2.5
- */
- public boolean isEmpty(SerializerProvider provider, T value) {
- return (value == null);
- }
-
/**
* Method that can be called to see whether this serializer instance
* will use Object Id to handle cyclic references.
@@ -228,7 +282,7 @@ public boolean usesObjectId() {
public boolean isUnwrappingSerializer() {
return false;
}
-
+
/**
* Accessor that can be used to determine if this serializer uses
* another serializer for actual serialization, by delegating
@@ -237,8 +291,6 @@ public boolean isUnwrappingSerializer() {
*
* @return Serializer this serializer delegates calls to, if null;
* null otherwise.
- *
- * @since 2.1
*/
public JsonSerializer> getDelegatee() {
return null;
@@ -251,23 +303,38 @@ public JsonSerializer> getDelegatee() {
* {@link com.fasterxml.jackson.databind.ser.BeanPropertyWriter}.
* Of standard Jackson serializers, only {@link com.fasterxml.jackson.databind.ser.BeanSerializer}
* exposes properties.
- *
- * @since 2.6
*/
public Iterator properties() {
return ClassUtil.emptyIterator();
}
/*
- /**********************************************************
+ /**********************************************************************
+ /* Accessors for introspecting handling of values
+ /**********************************************************************
+ */
+
+ /**
+ * Method called to check whether given serializable value is
+ * considered "empty" value (for purposes of suppressing serialization
+ * of empty values).
+ *
+ * Default implementation will consider only null values to be empty.
+ */
+ public boolean isEmpty(SerializerProvider provider, T value)
+ throws IOException
+ {
+ return (value == null);
+ }
+
+ /*
+ /**********************************************************************
/* Default JsonFormatVisitable implementation
- /**********************************************************
+ /**********************************************************************
*/
/**
* Default implementation simply calls {@link JsonFormatVisitorWrapper#expectAnyFormat(JavaType)}.
- *
- * @since 2.1
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type)
@@ -277,9 +344,9 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
}
/*
- /**********************************************************
+ /**********************************************************************
/* Helper class(es)
- /**********************************************************
+ /**********************************************************************
*/
/**
diff --git a/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java
index 217527d412..12c5a2bac3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java
@@ -9,6 +9,32 @@
*/
public abstract class KeyDeserializer
{
+ /*
+ /**********************************************************
+ /* Initialization, with former `ResolvableDeserializer`
+ /**********************************************************
+ */
+
+ /**
+ * Method called after deserializer instance has been constructed
+ * (and registered as necessary by provider objects),
+ * but before it has returned it to the caller.
+ * Called object can then resolve its dependencies to other types,
+ * including self-references (direct or indirect).
+ *
+ * @param ctxt Context to use for accessing configuration, resolving
+ * secondary deserializers
+ */
+ public void resolve(DeserializationContext ctxt) throws JsonMappingException {
+ // Default implementation does nothing
+ }
+
+ /*
+ /**********************************************************
+ /* Main API
+ /**********************************************************
+ */
+
/**
* Method called to deserialize a {@link java.util.Map} key from JSON property name.
*/
diff --git a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
index 9b7bb96f34..ab8d33980e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
@@ -46,9 +46,9 @@ public enum MapperFeature implements ConfigFeature
* precedence than setters, so they are only used if no
* setter is found for the Map/Collection property.
*
- * Feature is enabled by default.
+ * Feature is disabled by default since 3.0 (with 2.x was enabled)
*/
- USE_GETTERS_AS_SETTERS(true),
+ USE_GETTERS_AS_SETTERS(false),
/**
* Feature that determines how transient
modifier for fields
@@ -58,99 +58,9 @@ public enum MapperFeature implements ConfigFeature
* Feature is disabled by default, meaning that existence of `transient`
* for a field does not necessarily lead to ignoral of getters or setters
* but just ignoring the use of field for access.
- *
- * @since 2.6
*/
PROPAGATE_TRANSIENT_MARKER(false),
- /*
- /******************************************************
- /* Introspection-based property auto-detection
- /******************************************************
- */
-
- /**
- * Feature that determines whether "creator" methods are
- * automatically detected by consider public constructors,
- * and static single argument methods with name "valueOf".
- * If disabled, only methods explicitly annotated are considered
- * creator methods (except for the no-arg default constructor which
- * is always considered a factory method).
- *
- * Note that this feature has lower precedence than per-class
- * annotations, and is only used if there isn't more granular
- * configuration available.
- *
- * Feature is enabled by default.
- */
- AUTO_DETECT_CREATORS(true),
-
- /**
- * Feature that determines whether non-static fields are recognized as
- * properties.
- * If yes, then all public member fields
- * are considered as properties. If disabled, only fields explicitly
- * annotated are considered property fields.
- *
- * Note that this feature has lower precedence than per-class
- * annotations, and is only used if there isn't more granular
- * configuration available.
- *
- * Feature is enabled by default.
- */
- AUTO_DETECT_FIELDS(true),
-
- /**
- * Feature that determines whether regular "getter" methods are
- * automatically detected based on standard Bean naming convention
- * or not. If yes, then all public zero-argument methods that
- * start with prefix "get"
- * are considered as getters.
- * If disabled, only methods explicitly annotated are considered getters.
- *
- * Note that since version 1.3, this does NOT include
- * "is getters" (see {@link #AUTO_DETECT_IS_GETTERS} for details)
- *
- * Note that this feature has lower precedence than per-class
- * annotations, and is only used if there isn't more granular
- * configuration available.
- *
- * Feature is enabled by default.
- */
- AUTO_DETECT_GETTERS(true),
-
- /**
- * Feature that determines whether "is getter" methods are
- * automatically detected based on standard Bean naming convention
- * or not. If yes, then all public zero-argument methods that
- * start with prefix "is", and whose return type is boolean
- * are considered as "is getters".
- * If disabled, only methods explicitly annotated are considered getters.
- *
- * Note that this feature has lower precedence than per-class
- * annotations, and is only used if there isn't more granular
- * configuration available.
- *
- * Feature is enabled by default.
- */
- AUTO_DETECT_IS_GETTERS(true),
-
- /**
- * Feature that determines whether "setter" methods are
- * automatically detected based on standard Bean naming convention
- * or not. If yes, then all public one-argument methods that
- * start with prefix "set"
- * are considered setters. If disabled, only methods explicitly
- * annotated are considered setters.
- *
- * Note that this feature has lower precedence than per-class
- * annotations, and is only used if there isn't more granular
- * configuration available.
- *
- * Feature is enabled by default.
- */
- AUTO_DETECT_SETTERS(true),
-
/**
* Feature that determines whether getters (getter methods)
* can be auto-detected if there is no matching mutator (setter,
@@ -171,8 +81,6 @@ public enum MapperFeature implements ConfigFeature
* explicitly annotated for such use.
*
* Feature is enabled by default, for backwards compatibility reasons.
- *
- * @since 2.2
*/
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
@@ -189,8 +97,6 @@ public enum MapperFeature implements ConfigFeature
* bean-style naming) or explicitly annotated.
*
* Feature is enabled by default.
- *
- * @since 2.2
*/
INFER_PROPERTY_MUTATORS(true),
@@ -208,8 +114,6 @@ public enum MapperFeature implements ConfigFeature
* for deserialization.
*
* Feature is enabled by default.
- *
- * @since 2.9
*/
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true),
@@ -258,8 +162,6 @@ public enum MapperFeature implements ConfigFeature
*
* Feature is enabled by default, for legacy reasons (it was the behavior
* until 2.6)
- *
- * @since 2.7
*/
OVERRIDE_PUBLIC_ACCESS_MODIFIERS(true),
@@ -286,6 +188,18 @@ public enum MapperFeature implements ConfigFeature
*/
USE_STATIC_TYPING(false),
+ /**
+ * Feature that enables inferring builder type bindings from the value type
+ * being deserialized. This requires that the generic type declaration on
+ * the value type match that on the builder exactly.
+ *
+ * Feature is disabled by default which means that deserialization does
+ * not support deserializing types via builders with type parameters.
+ *
+ * See: https://github.com/FasterXML/jackson-databind/issues/921
+ */
+ INFER_BUILDER_TYPE_BINDINGS(false),
+
/**
* Feature that specifies whether the declared base type of a polymorphic value
* is to be used as the "default" implementation, if no explicit default class
@@ -364,8 +278,6 @@ public enum MapperFeature implements ConfigFeature
* letters. Overhead for names that are already lower-case should be negligible however.
*
* Feature is disabled by default.
- *
- * @since 2.5
*/
ACCEPT_CASE_INSENSITIVE_PROPERTIES(false),
@@ -377,8 +289,6 @@ public enum MapperFeature implements ConfigFeature
* explicit override) do not need to match.
*
* Feature is disabled by default.
- *
- * @since 2.9
*/
ACCEPT_CASE_INSENSITIVE_ENUMS(false),
@@ -391,91 +301,24 @@ public enum MapperFeature implements ConfigFeature
* If disabled, wrapper name is only used for wrapping (if anything).
*
* Feature is disabled by default.
- *
- * @since 2.1
*/
USE_WRAPPER_NAME_AS_PROPERTY_NAME(false),
- /**
- * Feature that may be enabled to enforce strict compatibility with
- * Bean name introspection, instead of slightly different mechanism
- * Jackson defaults to.
- * Specific difference is that Jackson always lower cases leading upper-case
- * letters, so "getURL()" becomes "url" property; whereas standard Bean
- * naming only lower-cases the first letter if it is NOT followed by
- * another upper-case letter (so "getURL()" would result in "URL" property).
- *
- * Feature is disabled by default for backwards compatibility purposes: earlier
- * Jackson versions used Jackson's own mechanism.
- *
- * @since 2.5
- */
- USE_STD_BEAN_NAMING(false),
-
/**
* Feature that when enabled will allow explicitly named properties (i.e., fields or methods
* annotated with {@link com.fasterxml.jackson.annotation.JsonProperty}("explicitName")) to
* be re-named by a {@link PropertyNamingStrategy}, if one is configured.
*
* Feature is disabled by default.
- *
- * @since 2.7
*/
ALLOW_EXPLICIT_PROPERTY_RENAMING(false),
- /*
- /******************************************************
- /* Coercion features
- /******************************************************
- */
-
- /**
- * Feature that determines whether coercions from secondary representations are allowed
- * for simple non-textual scalar types: numbers and booleans. This includes `primitive`
- * types and their wrappers, but excludes `java.lang.String` and date/time types.
- *
- * When feature is disabled, only strictly compatible input may be bound: numbers for
- * numbers, boolean values for booleans. When feature is enabled, conversions from
- * JSON String are allowed, as long as textual value matches (for example, String
- * "true" is allowed as equivalent of JSON boolean token `true`; or String "1.0"
- * for `double`).
- *
- * Note that it is possible that other configurability options can override this
- * in closer scope (like on per-type or per-property basis); this is just the global
- * default.
- *
- * Feature is enabled by default (for backwards compatibility since this was the
- * default behavior)
- *
- * @since 2.9
- */
- ALLOW_COERCION_OF_SCALARS(true),
-
/*
/******************************************************
/* Other features
/******************************************************
*/
- /**
- * Feature that determines whether multiple registrations of same module
- * should be ignored or not; if enabled, only the first registration call
- * results in module being called, and possible duplicate calls are silently
- * ignored; if disabled, no checking is done and all registration calls are
- * dispatched to module.
- *
- * Definition of "same module" is based on using {@link Module#getTypeId()};
- * modules with same non-null type id
are considered same for
- * purposes of duplicate registration. This also avoids having to keep track
- * of actual module instances; only ids will be kept track of (and only if
- * this feature is enabled).
- *
- * Feature is enabled by default.
- *
- * @since 2.5
- */
- IGNORE_DUPLICATE_MODULE_REGISTRATIONS(true),
-
/**
* Setting that determines what happens if an attempt is made to explicitly
* "merge" value of a property, where value does not support merging; either
@@ -485,8 +328,6 @@ public enum MapperFeature implements ConfigFeature
* Feature is disabled by default since non-mergeable property types are ignored
* even if defaults call for merging, and usually explicit per-type or per-property
* settings for such types should result in an exception.
- *
- * @since 2.9
*/
IGNORE_MERGE_FOR_UNMERGEABLE(true)
diff --git a/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java b/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
index 06a4758bed..15e72414fa 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
@@ -5,6 +5,7 @@
import java.util.*;
import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.exc.RuntimeJsonMappingException;
/**
* Iterator exposed by {@link ObjectMapper} when binding sequence of
@@ -17,9 +18,9 @@ public class MappingIterator implements Iterator, Closeable
new MappingIterator(null, null, null, null, false, null);
/*
- /**********************************************************
+ /**********************************************************************
/* State constants
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -45,9 +46,9 @@ public class MappingIterator implements Iterator, Closeable
protected final static int STATE_HAS_VALUE = 3;
/*
- /**********************************************************
+ /**********************************************************************
/* Configuration
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -76,7 +77,7 @@ public class MappingIterator implements Iterator, Closeable
* Context to resynchronize to, in case an exception is encountered
* but caller wants to try to read more elements.
*/
- protected final JsonStreamContext _seqContext;
+ protected final TokenStreamContext _seqContext;
/**
* If not null, "value to update" instead of creating a new instance
@@ -92,9 +93,9 @@ public class MappingIterator implements Iterator, Closeable
protected final boolean _closeParser;
/*
- /**********************************************************
+ /**********************************************************************
/* Parsing state
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -103,9 +104,9 @@ public class MappingIterator implements Iterator, Closeable
protected int _state;
/*
- /**********************************************************
+ /**********************************************************************
/* Construction
- /**********************************************************
+ /**********************************************************************
*/
/**
@@ -144,7 +145,7 @@ protected MappingIterator(JavaType type, JsonParser p, DeserializationContext ct
_seqContext = null;
_state = STATE_CLOSED;
} else {
- JsonStreamContext sctxt = p.getParsingContext();
+ TokenStreamContext sctxt = p.getParsingContext();
if (managedParser && p.isExpectedStartArrayToken()) {
// If pointing to START_ARRAY, context should be that ARRAY
p.clearCurrentToken();
@@ -152,7 +153,7 @@ protected MappingIterator(JavaType type, JsonParser p, DeserializationContext ct
// regardless, recovery context should be whatever context we have now,
// with sole exception of pointing to a start marker, in which case it's
// the parent
- JsonToken t = p.getCurrentToken();
+ JsonToken t = p.currentToken();
if ((t == JsonToken.START_OBJECT) || (t == JsonToken.START_ARRAY)) {
sctxt = sctxt.getParent();
}
@@ -168,9 +169,9 @@ protected static MappingIterator emptyIterator() {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Basic iterator impl
- /**********************************************************
+ /**********************************************************************
*/
@Override
@@ -191,9 +192,9 @@ public T next()
try {
return nextValue();
} catch (JsonMappingException e) {
- throw new RuntimeJsonMappingException(e.getMessage(), e);
+ return _handleMappingException(e);
} catch (IOException e) {
- throw new RuntimeException(e.getMessage(), e);
+ return _handleIOException(e);
}
}
@@ -213,15 +214,11 @@ public void close() throws IOException {
}
/*
- /**********************************************************
+ /**********************************************************************
/* Extended API, iteration
- /**********************************************************
+ /**********************************************************************
*/
-
- /*
- */
-
/**
* Equivalent of {@link #next} but one that may throw checked
* exceptions from Jackson due to invalid input.
@@ -235,7 +232,7 @@ public boolean hasNextValue() throws IOException
_resync();
// fall-through
case STATE_MAY_HAVE_VALUE:
- JsonToken t = _parser.getCurrentToken();
+ JsonToken t = _parser.currentToken();
if (t == null) { // un-initialized or cleared; find next
t = _parser.nextToken();
// If EOF, no more, or if we hit END_ARRAY (although we don't clear the token).
@@ -283,10 +280,8 @@ public T nextValue() throws IOException
return value;
} finally {
_state = nextState;
- /* 24-Mar-2015, tatu: As per [#733], need to mark token consumed no
- * matter what, to avoid infinite loop for certain failure cases.
- * For 2.6 need to improve further.
- */
+ // 24-Mar-2015, tatu: As per [#733], need to mark token consumed no
+ // matter what, to avoid infinite loop for certain failure cases.
_parser.clearCurrentToken();
}
}
@@ -296,8 +291,6 @@ public T nextValue() throws IOException
* this iterator; resulting container will be a {@link java.util.ArrayList}.
*
* @return List of entries read
- *
- * @since 2.2
*/
public List readAll() throws IOException {
return readAll(new ArrayList());
@@ -308,8 +301,6 @@ public List readAll() throws IOException {
* this iterator
*
* @return List of entries read (same as passed-in argument)
- *
- * @since 2.2
*/
public > L readAll(L resultList) throws IOException
{
@@ -322,8 +313,6 @@ public > L readAll(L resultList) throws IOException
/**
* Convenience method for reading all entries accessible via
* this iterator
- *
- * @since 2.5
*/
public > C readAll(C results) throws IOException
{
@@ -334,15 +323,13 @@ public > C readAll(C results) throws IOException
}
/*
- /**********************************************************
+ /**********************************************************************
/* Extended API, accessors
- /**********************************************************
+ /**********************************************************************
*/
/**
* Accessor for getting underlying parser this iterator uses.
- *
- * @since 2.2
*/
public JsonParser getParser() {
return _parser;
@@ -352,8 +339,6 @@ public JsonParser getParser() {
* Accessor for accessing {@link FormatSchema} that the underlying parser
* (as per {@link #getParser}) is using, if any; only parser of schema-aware
* formats use schemas.
- *
- * @since 2.2
*/
public FormatSchema getParserSchema() {
return _parser.getSchema();
@@ -366,17 +351,15 @@ public FormatSchema getParserSchema() {
*
*
* @return Location of the input stream of the underlying parser
- *
- * @since 2.2.1
*/
public JsonLocation getCurrentLocation() {
return _parser.getCurrentLocation();
}
/*
- /**********************************************************
+ /**********************************************************************
/* Helper methods
- /**********************************************************
+ /**********************************************************************
*/
protected void _resync() throws IOException
diff --git a/src/main/java/com/fasterxml/jackson/databind/MappingJsonFactory.java b/src/main/java/com/fasterxml/jackson/databind/MappingJsonFactory.java
deleted file mode 100644
index a7939f63e1..0000000000
--- a/src/main/java/com/fasterxml/jackson/databind/MappingJsonFactory.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.fasterxml.jackson.databind;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.core.format.InputAccessor;
-import com.fasterxml.jackson.core.format.MatchStrength;
-
-/**
- * Sub-class of {@link JsonFactory} that will create a proper
- * {@link ObjectCodec} to allow seam-less conversions between
- * JSON content and Java objects (POJOs).
- * The only addition to regular {@link JsonFactory} currently
- * is that {@link ObjectMapper} is constructed and passed as
- * the codec to use.
- */
-public class MappingJsonFactory
- extends JsonFactory
-{
- private static final long serialVersionUID = -1; // since 2.7
-
- public MappingJsonFactory()
- {
- this(null);
- }
-
- public MappingJsonFactory(ObjectMapper mapper)
- {
- super(mapper);
- if (mapper == null) {
- setCodec(new ObjectMapper(this));
- }
- }
-
- public MappingJsonFactory(JsonFactory src, ObjectMapper mapper)
- {
- super(src, mapper);
- if (mapper == null) {
- setCodec(new ObjectMapper(this));
- }
- }
-
- /**
- * We'll override the method to return more specific type; co-variance
- * helps here
- */
- @Override
- public final ObjectMapper getCodec() { return (ObjectMapper) _objectCodec; }
-
- // @since 2.1
- @Override
- public JsonFactory copy()
- {
- _checkInvalidCopy(MappingJsonFactory.class);
- // note: as with base class, must NOT copy mapper reference
- return new MappingJsonFactory(this, null);
- }
-
- /*
- /**********************************************************
- /* Format detection functionality (since 1.8)
- /**********************************************************
- */
-
- /**
- * Sub-classes need to override this method
- */
- @Override
- public String getFormatName()
- {
- /* since non-JSON factories typically should not extend this class,
- * let's just always return JSON as name.
- */
- return FORMAT_NAME_JSON;
- }
-
- /**
- * Sub-classes need to override this method
- */
- @Override
- public MatchStrength hasFormat(InputAccessor acc) throws IOException
- {
- if (getClass() == MappingJsonFactory.class) {
- return hasJSONFormat(acc);
- }
- return null;
- }
-}
diff --git a/src/main/java/com/fasterxml/jackson/databind/Module.java b/src/main/java/com/fasterxml/jackson/databind/Module.java
index 5884e6b3b5..f7139cdef8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/Module.java
+++ b/src/main/java/com/fasterxml/jackson/databind/Module.java
@@ -1,15 +1,13 @@
package com.fasterxml.jackson.databind;
import java.util.Collection;
+import java.util.function.UnaryOperator;
import com.fasterxml.jackson.core.*;
+
+import com.fasterxml.jackson.databind.cfg.MapperBuilder;
import com.fasterxml.jackson.databind.cfg.MutableConfigOverride;
-import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
-import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
-import com.fasterxml.jackson.databind.deser.Deserializers;
-import com.fasterxml.jackson.databind.deser.KeyDeserializers;
-import com.fasterxml.jackson.databind.deser.ValueInstantiators;
-import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
+import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.Serializers;
@@ -25,11 +23,11 @@ public abstract class Module
implements Versioned
{
/*
- /**********************************************************
+ /**********************************************************************
/* Simple accessors
- /**********************************************************
+ /**********************************************************************
*/
-
+
/**
* Method that returns a display that can be used by Jackson
* for informational purposes, as well as in associating extensions with
@@ -47,38 +45,28 @@ public abstract class Module
/**
* Method that returns an id that may be used to determine if two {@link Module}
* instances are considered to be of same type, for purpose of preventing
- * multiple registrations of "same type of" module
- * (see {@link com.fasterxml.jackson.databind.MapperFeature#IGNORE_DUPLICATE_MODULE_REGISTRATIONS})
- * If `null` is returned, every instance is considered unique.
- * If non-null value is returned, equality of id Objects is used to check whether
- * modules should be considered to be "of same type"
+ * multiple registrations of "same" module,
*
* Default implementation returns value of class name ({@link Class#getName}).
*
- * @since 2.5
+ * @since 3.0
*/
- public Object getTypeId() {
+ public Object getRegistrationId() {
return getClass().getName();
}
-
+
/*
- /**********************************************************
+ /**********************************************************************
/* Life-cycle: registration
- /**********************************************************
+ /**********************************************************************
*/
-
+
/**
* Method called by {@link ObjectMapper} when module is registered.
* It is called to let module register functionality it provides,
* using callback methods passed-in context object exposes.
*/
public abstract void setupModule(SetupContext context);
-
- /*
- /**********************************************************
- /* Helper types
- /**********************************************************
- */
/**
* Interface Jackson exposes to modules for purpose of registering
@@ -90,11 +78,11 @@ public Object getTypeId() {
public static interface SetupContext
{
/*
- /**********************************************************
+ /******************************************************************
/* Simple accessors
- /**********************************************************
+ /******************************************************************
*/
-
+
/**
* Method that returns version information about {@link ObjectMapper}
* that implements this context. Modules can use this to choose
@@ -103,9 +91,14 @@ public static interface SetupContext
*/
public Version getMapperVersion();
+ /**
+ * @since 3.0
+ */
+ public String getFormatName();
+
/**
* Fallback access method that allows modules to refer to the
- * {@link ObjectMapper} that provided this context.
+ * {@link MapperBuilder} that provided this context.
* It should NOT be needed by most modules; and ideally should
* not be used -- however, there may be cases where this may
* be necessary due to various design constraints.
@@ -115,14 +108,13 @@ public static interface SetupContext
* to allow access to new features in cases where Module API
* has not yet been extended, or there are oversights.
*
- * Return value is chosen to not leak dependency to {@link ObjectMapper};
- * however, instance will always be of that type.
- * This is why return value is declared generic, to allow caller to
- * specify context to often avoid casting.
- *
- * @since 2.0
+ * Return value is chosen to force casting, to make caller aware that
+ * this is a fallback accessor, used only when everything else fails:
+ * type is, however, guaranteed to be {@link MapperBuilder} (and more
+ * specifally format-specific subtype that mapper constructed, in case
+ * format-specific access is needed).
*/
- public C getOwner();
+ public Object getOwner();
/**
* Accessor for finding {@link TypeFactory} that is currently configured
@@ -130,27 +122,22 @@ public static interface SetupContext
*
* NOTE: since it is possible that other modules might change or replace
* TypeFactory, use of this method adds order-dependency for registrations.
- *
- * @since 2.0
*/
- public TypeFactory getTypeFactory();
-
+ public TypeFactory typeFactory();
+
+ public TokenStreamFactory tokenStreamFactory();
+
public boolean isEnabled(MapperFeature f);
-
public boolean isEnabled(DeserializationFeature f);
-
public boolean isEnabled(SerializationFeature f);
-
- public boolean isEnabled(JsonFactory.Feature f);
-
- public boolean isEnabled(JsonParser.Feature f);
-
- public boolean isEnabled(JsonGenerator.Feature f);
+ public boolean isEnabled(TokenStreamFactory.Feature f);
+ public boolean isEnabled(StreamReadFeature f);
+ public boolean isEnabled(StreamWriteFeature f);
/*
- /**********************************************************
+ /******************************************************************
/* Mutant accessors
- /**********************************************************
+ /******************************************************************
*/
/**
@@ -167,108 +154,102 @@ public static interface SetupContext
* to change the default format to use for properties of type
* {@link java.util.Date} (possibly further overridden by per-property
* annotations)
- *
- * @since 2.8
*/
public MutableConfigOverride configOverride(Class> type);
-
+
/*
- /**********************************************************
- /* Handler registration; serializers/deserializers
- /**********************************************************
+ /******************************************************************
+ /* Handler registration; deserializers, related
+ /******************************************************************
*/
/**
* Method that module can use to register additional deserializers to use for
* handling types.
- *
+ *
* @param d Object that can be called to find deserializer for types supported
* by module (null returned for non-supported types)
*/
- public void addDeserializers(Deserializers d);
+ public SetupContext addDeserializers(Deserializers d);
/**
* Method that module can use to register additional deserializers to use for
* handling Map key values (which are separate from value deserializers because
* they are always serialized from String values)
*/
- public void addKeyDeserializers(KeyDeserializers s);
+ public SetupContext addKeyDeserializers(KeyDeserializers s);
+ /**
+ * Method that module can use to register additional modifier objects to
+ * customize configuration and construction of bean deserializers.
+ *
+ * @param mod Modifier to register
+ */
+ public SetupContext addDeserializerModifier(BeanDeserializerModifier mod);
+
+ /**
+ * Method that module can use to register additional {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s,
+ * by adding {@link ValueInstantiators} object that gets called when
+ * instantatiator is needed by a deserializer.
+ *
+ * @param instantiators Object that can provide {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s for
+ * constructing POJO values during deserialization
+ */
+ public SetupContext addValueInstantiators(ValueInstantiators instantiators);
+
+ /*
+ /******************************************************************
+ /* Handler registration; serializers, related
+ /******************************************************************
+ */
+
/**
* Method that module can use to register additional serializers to use for
* handling types.
- *
+ *
* @param s Object that can be called to find serializer for types supported
* by module (null returned for non-supported types)
*/
- public void addSerializers(Serializers s);
+ public SetupContext addSerializers(Serializers s);
/**
* Method that module can use to register additional serializers to use for
* handling Map key values (which are separate from value serializers because
* they must write JsonToken.FIELD_NAME
instead of String value).
*/
- public void addKeySerializers(Serializers s);
-
- /*
- /**********************************************************
- /* Handler registration; other
- /**********************************************************
- */
-
- /**
- * Method that module can use to register additional modifier objects to
- * customize configuration and construction of bean deserializers.
- *
- * @param mod Modifier to register
- */
- public void addBeanDeserializerModifier(BeanDeserializerModifier mod);
+ public SetupContext addKeySerializers(Serializers s);
/**
* Method that module can use to register additional modifier objects to
* customize configuration and construction of bean serializers.
- *
+ *
* @param mod Modifier to register
*/
- public void addBeanSerializerModifier(BeanSerializerModifier mod);
-
- /**
- * Method that module can use to register additional
- * {@link AbstractTypeResolver} instance, to handle resolution of
- * abstract to concrete types (either by defaulting, or by materializing).
- *
- * @param resolver Resolver to add.
- */
- public void addAbstractTypeResolver(AbstractTypeResolver resolver);
+ public SetupContext addSerializerModifier(BeanSerializerModifier mod);
/**
- * Method that module can use to register additional
- * {@link TypeModifier} instance, which can augment {@link com.fasterxml.jackson.databind.JavaType}
- * instances constructed by {@link com.fasterxml.jackson.databind.type.TypeFactory}.
- *
- * @param modifier to add
+ * Method that module can use to override handler called to write JSON Object key
+ * for {@link java.util.Map} values.
+ *
+ * @param ser Serializer called to write output for JSON Object key of which value
+ * on Java side is `null`
*/
- public void addTypeModifier(TypeModifier modifier);
+ public SetupContext overrideDefaultNullKeySerializer(JsonSerializer> ser);
/**
- * Method that module can use to register additional {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s,
- * by adding {@link ValueInstantiators} object that gets called when
- * instantatiator is needed by a deserializer.
- *
- * @param instantiators Object that can provide {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}s for
- * constructing POJO values during deserialization
+ * Method that module can use to override handler called to write Java `null` as
+ * a value (Property or Map value, Collection/array element).
+ *
+ * @param ser Serializer called to write output for Java `null` as value (as distinct from
+ * key_
*/
- public void addValueInstantiators(ValueInstantiators instantiators);
+ public SetupContext overrideDefaultNullValueSerializer(JsonSerializer> ser);
- /**
- * Method for replacing the default class introspector with a derived class that
- * overrides specific behavior.
- *
- * @param ci Derived class of ClassIntrospector with overriden behavior
- *
- * @since 2.2
+ /*
+ /******************************************************************
+ /* Handler registration, annotation introspectors
+ /******************************************************************
*/
- public void setClassIntrospector(ClassIntrospector ci);
/**
* Method for registering specified {@link AnnotationIntrospector} as the highest
@@ -277,7 +258,7 @@ public static interface SetupContext
*
* @param ai Annotation introspector to register.
*/
- public void insertAnnotationIntrospector(AnnotationIntrospector ai);
+ public SetupContext insertAnnotationIntrospector(AnnotationIntrospector ai);
/**
* Method for registering specified {@link AnnotationIntrospector} as the lowest
@@ -286,28 +267,71 @@ public static interface SetupContext
*
* @param ai Annotation introspector to register.
*/
- public void appendAnnotationIntrospector(AnnotationIntrospector ai);
+ public SetupContext appendAnnotationIntrospector(AnnotationIntrospector ai);
+
+ /*
+ /******************************************************************
+ /* Type handling
+ /******************************************************************
+ */
+
+ /**
+ * Method that module can use to register additional
+ * {@link AbstractTypeResolver} instance, to handle resolution of
+ * abstract to concrete types (either by defaulting, or by materializing).
+ *
+ * @param resolver Resolver to add.
+ */
+ public SetupContext addAbstractTypeResolver(AbstractTypeResolver resolver);
+
+ /**
+ * Method that module can use to register additional
+ * {@link TypeModifier} instance, which can augment {@link com.fasterxml.jackson.databind.JavaType}
+ * instances constructed by {@link com.fasterxml.jackson.databind.type.TypeFactory}.
+ *
+ * @param modifier to add
+ */
+ public SetupContext addTypeModifier(TypeModifier modifier);
/**
* Method for registering specified classes as subtypes (of supertype(s)
* they have)
*/
- public void registerSubtypes(Class>... subtypes);
+ public SetupContext registerSubtypes(Class>... subtypes);
/**
* Method for registering specified classes as subtypes (of supertype(s)
* they have), using specified type names.
*/
- public void registerSubtypes(NamedType... subtypes);
+ public SetupContext registerSubtypes(NamedType... subtypes);
/**
* Method for registering specified classes as subtypes (of supertype(s)
* they have)
+ */
+ public SetupContext registerSubtypes(Collection> subtypes);
+
+ /*
+ /******************************************************************
+ /* Handler registration, other
+ /******************************************************************
+ */
+
+ /**
+ * Add a deserialization problem handler
*
- * @since 2.9
+ * @param handler The deserialization problem handler
*/
- public void registerSubtypes(Collection> subtypes);
-
+ public SetupContext addHandler(DeserializationProblemHandler handler);
+
+ /**
+ * Replace default {@link InjectableValues} that have been configured to be
+ * used for mapper being built.
+ *
+ * @since 3.0
+ */
+ public SetupContext overrideInjectableValues(UnaryOperator v);
+
/**
* Method used for defining mix-in annotations to use for augmenting
* specified class or interface.
@@ -326,21 +350,6 @@ public static interface SetupContext
* @param mixinSource Class (or interface) whose annotations are to
* be "added" to target's annotations, overriding as necessary
*/
- public void setMixInAnnotations(Class> target, Class> mixinSource);
-
- /**
- * Add a deserialization problem handler
- *
- * @param handler The deserialization problem handler
- */
- public void addDeserializationProblemHandler(DeserializationProblemHandler handler);
-
- /**
- * Method that may be used to override naming strategy that is used
- * by {@link ObjectMapper}.
- *
- * @since 2.3
- */
- public void setNamingStrategy(PropertyNamingStrategy naming);
+ public SetupContext setMixIn(Class> target, Class> mixinSource);
}
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index 1a48ed4bed..14ef08afec 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -3,34 +3,30 @@
import java.io.*;
import java.lang.reflect.Type;
import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.text.DateFormat;
-import java.util.*;
+import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
-import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SegmentedStringWriter;
+import com.fasterxml.jackson.core.json.JsonFactory;
import com.fasterxml.jackson.core.type.ResolvedType;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.util.*;
+
import com.fasterxml.jackson.databind.cfg.*;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.introspect.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
-import com.fasterxml.jackson.databind.jsontype.*;
-import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver;
-import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
+import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
import com.fasterxml.jackson.databind.node.*;
import com.fasterxml.jackson.databind.ser.*;
import com.fasterxml.jackson.databind.type.*;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.RootNameLookup;
-import com.fasterxml.jackson.databind.util.StdDateFormat;
import com.fasterxml.jackson.databind.util.TokenBuffer;
/**
@@ -38,11 +34,22 @@
* either to and from basic POJOs (Plain Old Java Objects), or to and from
* a general-purpose JSON Tree Model ({@link JsonNode}), as well as
* related functionality for performing conversions.
- * It is also highly customizable to work both with different styles of JSON
- * content, and to support more advanced Object concepts such as
- * polymorphism and Object identity.
- * ObjectMapper
also acts as a factory for more advanced {@link ObjectReader}
- * and {@link ObjectWriter} classes.
+ * In addition to directly reading and writing JSON (and with different underlying
+ * {@link TokenStreamFactory} configuration, other formats), it is also the
+ * mechanism for creating {@link ObjectReader}s and {@link ObjectWriter}s which
+ * offer more advancing reading/writing functionality.
+ *
+ * Construction of mapper instances proceeds either via no-arguments constructor
+ * (producing instance with default configuration); or through one of two build
+ * methods.
+ * First build method is the static builder()
on exact type
+ * and second {@link #rebuild()} method method on an existing mapper.
+ * Former starts with default configuration (same as one that no-arguments constructor
+ * created mapper has), and latter starts with configuration of the mapper it is called
+ * on.
+ * In both cases, after configuration (including addition of {@link Module}s) is complete,
+ * instance is created by calling {@link MapperBuilder#build()} method.
+ *
* Mapper (and {@link ObjectReader}s, {@link ObjectWriter}s it constructs) will
* use instances of {@link JsonParser} and {@link JsonGenerator}
* for implementing actual reading/writing of JSON.
@@ -67,37 +74,8 @@
// and find values by, for example, using a {@link com.fasterxml.jackson.core.JsonPointer} expression:
int age = root.at("/personal/age").getValueAsInt();
- *
- * The main conversion API is defined in {@link ObjectCodec}, so that
- * implementation details of this class need not be exposed to
- * streaming parser and generator classes. Usage via {@link ObjectCodec} is,
- * however, usually only for cases where dependency to {@link ObjectMapper} is
- * either not possible (from Streaming API), or undesireable (when only relying
- * on Streaming API).
*
- * Mapper instances are fully thread-safe provided that ALL configuration of the
- * instance occurs before ANY read or write calls. If configuration of a mapper instance
- * is modified after first usage, changes may or may not take effect, and configuration
- * calls themselves may fail.
- * If you need to use different configuration, you have two main possibilities:
- *
- * Construct and use {@link ObjectReader} for reading, {@link ObjectWriter} for writing.
- * Both types are fully immutable and you can freely create new instances with different
- * configuration using either factory methods of {@link ObjectMapper}, or readers/writers
- * themselves. Construction of new {@link ObjectReader}s and {@link ObjectWriter}s is
- * a very light-weight operation so it is usually appropriate to create these on per-call
- * basis, as needed, for configuring things like optional indentation of JSON.
- *
- * If the specific kind of configurability is not available via {@link ObjectReader} and
- * {@link ObjectWriter}, you may need to use multiple {@link ObjectMapper} instead (for example:
- * you cannot change mix-in annotations on-the-fly; or, set of custom (de)serializers).
- * To help with this usage, you may want to use method {@link #copy()} which creates a clone
- * of the mapper with specific configuration, and allows configuration of the copied instance
- * before it gets used. Note that {@link #copy} operation is as expensive as constructing
- * a new {@link ObjectMapper} instance: if possible, you should still pool and reuse mappers
- * if you intend to use them for multiple operations.
- *
- *
+ * Mapper instances are fully thread-safe as of Jackson 3.0.
*
* Note on caching: root-level deserializers are always cached, and accessed
* using full (generics-aware) type information. This is different from
@@ -108,176 +86,63 @@
* produce differing deserializers), and that the performance impact
* greatest at root level (since it'll essentially cache the full
* graph of deserializers involved).
- *
- * Notes on security: use "default typing" feature (see {@link #enableDefaultTyping()})
- * is a potential security risk, if used with untrusted content (content generated by
- * untrusted external parties). If so, you may want to construct a custom
- * {@link TypeResolverBuilder} implementation to limit possible types to instantiate,
- * (using {@link #setDefaultTyping}).
*/
public class ObjectMapper
- extends ObjectCodec
implements Versioned,
- java.io.Serializable // as of 2.1
+ java.io.Serializable
{
- private static final long serialVersionUID = 2L; // as of 2.9
+ private static final long serialVersionUID = 3L;
/*
- /**********************************************************
+ /**********************************************************************
/* Helper classes, enums
- /**********************************************************
+ /**********************************************************************
*/
/**
- * Enumeration used with {@link ObjectMapper#enableDefaultTyping()}
- * to specify what kind of types (classes) default typing should
- * be used for. It will only be used if no explicit type information
- * is found, but this enumeration further limits subset of those types.
- *
- * Since 2.4 there are special exceptions for JSON Tree model
- * types (sub-types of {@link TreeNode}: default typing is never
- * applied to them.
- * Since 2.8(.4) additional checks are made to avoid attempts at default
- * typing primitive-valued properties.
- *
- * NOTE: use of Default Typing can be a potential security risk if incoming
- * content comes from untrusted sources, and it is recommended that this
- * is either not done, or, if enabled, use {@link #setDefaultTyping}
- * passing a custom {@link TypeResolverBuilder} implementation that white-lists
- * legal types to use.
- */
- public enum DefaultTyping {
- /**
- * This value means that only properties that have
- * {@link java.lang.Object} as declared type (including
- * generic types without explicit type) will use default
- * typing.
- */
- JAVA_LANG_OBJECT,
-
- /**
- * Value that means that default typing will be used for
- * properties with declared type of {@link java.lang.Object}
- * or an abstract type (abstract class or interface).
- * Note that this does not include array types.
- *
- * Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes.
- */
- OBJECT_AND_NON_CONCRETE,
-
- /**
- * Value that means that default typing will be used for
- * all types covered by {@link #OBJECT_AND_NON_CONCRETE}
- * plus all array types for them.
- *
- * Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes.
- */
- NON_CONCRETE_AND_ARRAYS,
-
- /**
- * Value that means that default typing will be used for
- * all non-final types, with exception of small number of
- * "natural" types (String, Boolean, Integer, Double), which
- * can be correctly inferred from JSON; as well as for
- * all arrays of non-final types.
- *
- * Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes.
- */
- NON_FINAL
- }
-
- /**
- * Customized {@link TypeResolverBuilder} that provides type resolver builders
- * used with so-called "default typing"
- * (see {@link ObjectMapper#enableDefaultTyping()} for details).
- *
- * Type resolver construction is based on configuration: implementation takes care
- * of only providing builders in cases where type information should be applied.
- * This is important since build calls may be sent for any and all types, and
- * type information should NOT be applied to all of them.
- */
- public static class DefaultTypeResolverBuilder
- extends StdTypeResolverBuilder
- implements java.io.Serializable
+ * Base implementation for "Vanilla" {@link ObjectMapper}, only defined to support
+ * backwards-compatibility with some of 2.x usage patterns.
+ */
+ private static class PrivateBuilder extends MapperBuilder
{
- private static final long serialVersionUID = 1L;
-
- /**
- * Definition of what types is this default typer valid for.
- */
- protected final DefaultTyping _appliesFor;
-
- public DefaultTypeResolverBuilder(DefaultTyping t) {
- _appliesFor = t;
+ public PrivateBuilder(TokenStreamFactory tsf) {
+ super(tsf);
}
@Override
- public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
- JavaType baseType, Collection subtypes)
- {
- return useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes) : null;
+ public ObjectMapper build() {
+ return new ObjectMapper(this);
}
@Override
- public TypeSerializer buildTypeSerializer(SerializationConfig config,
- JavaType baseType, Collection subtypes)
- {
- return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null;
+ protected MapperBuilderState _saveState() {
+ return new StateImpl(this);
}
- /**
- * Method called to check if the default type handler should be
- * used for given type.
- * Note: "natural types" (String, Boolean, Integer, Double) will never
- * use typing; that is both due to them being concrete and final,
- * and since actual serializers and deserializers will also ignore any
- * attempts to enforce typing.
- */
- public boolean useForType(JavaType t)
- {
- // 03-Oct-2016, tatu: As per [databind#1395], need to skip
- // primitive types too, regardless
- if (t.isPrimitive()) {
- return false;
+ public PrivateBuilder(MapperBuilderState state) {
+ super(state);
+ }
+
+ // We also need actual instance of state as base class can not implement logic
+ // for reinstating mapper (via mapper builder) from state.
+ static class StateImpl extends MapperBuilderState {
+ private static final long serialVersionUID = 3L;
+
+ public StateImpl(PrivateBuilder b) {
+ super(b);
}
- switch (_appliesFor) {
- case NON_CONCRETE_AND_ARRAYS:
- while (t.isArrayType()) {
- t = t.getContentType();
- }
- // fall through
- case OBJECT_AND_NON_CONCRETE:
- // 19-Apr-2016, tatu: ReferenceType like Optional also requires similar handling:
- while (t.isReferenceType()) {
- t = t.getReferencedType();
- }
- return t.isJavaLangObject()
- || (!t.isConcrete()
- // [databind#88] Should not apply to JSON tree models:
- && !TreeNode.class.isAssignableFrom(t.getRawClass()));
-
- case NON_FINAL:
- while (t.isArrayType()) {
- t = t.getContentType();
- }
- // 19-Apr-2016, tatu: ReferenceType like Optional also requires similar handling:
- while (t.isReferenceType()) {
- t = t.getReferencedType();
- }
- // [databind#88] Should not apply to JSON tree models:
- return !t.isFinal() && !TreeNode.class.isAssignableFrom(t.getRawClass());
- default:
- //case JAVA_LANG_OBJECT:
- return t.isJavaLangObject();
+ @Override
+ protected Object readResolve() {
+ return new PrivateBuilder(this).build();
}
}
}
/*
- /**********************************************************
+ /**********************************************************************
/* Internal constants, singletons
- /**********************************************************
+ /**********************************************************************
*/
// Quick little shortcut, to avoid having to use global TypeFactory instance...
@@ -287,150 +152,72 @@ public boolean useForType(JavaType t)
SimpleType.constructUnsafe(JsonNode.class);
// TypeFactory.defaultInstance().constructType(JsonNode.class);
- // 16-May-2009, tatu: Ditto ^^^
- protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector();
-
- /**
- * Base settings contain defaults used for all {@link ObjectMapper}
- * instances.
- */
- protected final static BaseSettings DEFAULT_BASE = new BaseSettings(
- null, // cannot share global ClassIntrospector any more (2.5+)
- DEFAULT_ANNOTATION_INTROSPECTOR,
- null, TypeFactory.defaultInstance(),
- null, StdDateFormat.instance, null,
- Locale.getDefault(),
- null, // to indicate "use Jackson default TimeZone" (UTC since Jackson 2.7)
- Base64Variants.getDefaultVariant() // 2.1
- );
-
/*
- /**********************************************************
+ /**********************************************************************
/* Configuration settings, shared
- /**********************************************************
+ /**********************************************************************
*/
/**
* Factory used to create {@link JsonParser} and {@link JsonGenerator}
* instances as necessary.
*/
- protected final JsonFactory _jsonFactory;
+ protected final TokenStreamFactory _streamFactory;
/**
* Specific factory used for creating {@link JavaType} instances;
* needed to allow modules to add more custom type handling
* (mostly to support types of non-Java JVM languages)
*/
- protected TypeFactory _typeFactory;
+ protected final TypeFactory _typeFactory;
/**
* Provider for values to inject in deserialized POJOs.
*/
- protected InjectableValues _injectableValues;
-
- /**
- * Thing used for registering sub-types, resolving them to
- * super/sub-types as needed.
- */
- protected SubtypeResolver _subtypeResolver;
-
- /**
- * Currently active per-type configuration overrides, accessed by
- * declared type of property.
- *
- * @since 2.9
- */
- protected final ConfigOverrides _configOverrides;
-
- /*
- /**********************************************************
- /* Configuration settings: mix-in annotations
- /**********************************************************
- */
-
- /**
- * Mapping that defines how to apply mix-in annotations: key is
- * the type to received additional annotations, and value is the
- * type that has annotations to "mix in".
- *
- * Annotations associated with the value classes will be used to
- * override annotations of the key class, associated with the
- * same field or method. They can be further masked by sub-classes:
- * you can think of it as injecting annotations between the target
- * class and its sub-classes (or interfaces)
- *
- * @since 2.6 (earlier was a simple {@link java.util.Map}
- */
- protected SimpleMixInResolver _mixIns;
+ protected final InjectableValues _injectableValues;
/*
- /**********************************************************
+ /**********************************************************************
/* Configuration settings, serialization
- /**********************************************************
- */
-
- /**
- * Configuration object that defines basic global
- * settings for the serialization process
+ /**********************************************************************
*/
- protected SerializationConfig _serializationConfig;
/**
- * Object that manages access to serializers used for serialization,
- * including caching.
- * It is configured with {@link #_serializerFactory} to allow
- * for constructing custom serializers.
+ * Factory used for constructing per-call {@link SerializerProvider}s.
*
* Note: while serializers are only exposed {@link SerializerProvider},
* mappers and readers need to access additional API defined by
* {@link DefaultSerializerProvider}
*/
- protected DefaultSerializerProvider _serializerProvider;
+ protected final SerializationContexts _serializationContexts;
/**
- * Serializer factory used for constructing serializers.
+ * Configuration object that defines basic global
+ * settings for the serialization process
*/
- protected SerializerFactory _serializerFactory;
+ protected final SerializationConfig _serializationConfig;
/*
- /**********************************************************
+ /**********************************************************************
/* Configuration settings, deserialization
- /**********************************************************
+ /**********************************************************************
*/
/**
- * Configuration object that defines basic global
- * settings for the serialization process
- */
- protected DeserializationConfig _deserializationConfig;
-
- /**
- * Blueprint context object; stored here to allow custom
- * sub-classes. Contains references to objects needed for
- * deserialization construction (cache, factory).
- */
- protected DefaultDeserializationContext _deserializationContext;
-
- /*
- /**********************************************************
- /* Module-related
- /**********************************************************
+ * Factory used for constructing per-call {@link DeserializationContext}s.
*/
+ protected final DeserializationContexts _deserializationContexts;
/**
- * Set of module types (as per {@link Module#getTypeId()} that have been
- * registered; kept track of iff {@link MapperFeature#IGNORE_DUPLICATE_MODULE_REGISTRATIONS}
- * is enabled, so that duplicate registration calls can be ignored
- * (to avoid adding same handlers multiple times, mostly).
- *
- * @since 2.5
+ * Configuration object that defines basic global
+ * settings for the serialization process
*/
- protected Set _registeredModuleTypes;
+ protected final DeserializationConfig _deserializationConfig;
/*
- /**********************************************************
+ /**********************************************************************
/* Caching
- /**********************************************************
+ /**********************************************************************
*/
/* Note: handling of serializers and deserializers is not symmetric;
@@ -451,250 +238,155 @@ public boolean useForType(JavaType t)
* (should very quickly converge to zero after startup), let's
* explicitly define a low concurrency setting.
*
- * Since version 1.5, these may are either "raw" deserializers (when
+ * These may are either "raw" deserializers (when
* no type information is needed for base type), or type-wrapped
* deserializers (if it is needed)
*/
- final protected ConcurrentHashMap> _rootDeserializers
+ protected final ConcurrentHashMap> _rootDeserializers
= new ConcurrentHashMap>(64, 0.6f, 2);
/*
- /**********************************************************
- /* Life-cycle: constructing instance
- /**********************************************************
+ /**********************************************************************
+ /* Saved state to allow re-building
+ /**********************************************************************
*/
/**
- * Default constructor, which will construct the default
- * {@link JsonFactory} as necessary, use
- * {@link SerializerProvider} as its
- * {@link SerializerProvider}, and
- * {@link BeanSerializerFactory} as its
- * {@link SerializerFactory}.
- * This means that it
- * can serialize all standard JDK types, as well as regular
- * Java Beans (based on method names and Jackson-specific annotations),
- * but does not support JAXB annotations.
+ * Minimal state retained to allow both re-building (by
+ * creating new builder) and JDK serialization of this mapper.
+ *
+ * @since 3.0
*/
- public ObjectMapper() {
- this(null, null, null);
- }
+ protected final MapperBuilderState _savedBuilderState;
- /**
- * Constructs instance that uses specified {@link JsonFactory}
- * for constructing necessary {@link JsonParser}s and/or
- * {@link JsonGenerator}s.
+ /*
+ /**********************************************************************
+ /* Life-cycle: legacy constructors
+ /**********************************************************************
*/
- public ObjectMapper(JsonFactory jf) {
- this(jf, null, null);
- }
/**
- * Copy-constructor, mostly used to support {@link #copy}.
- *
- * @since 2.1
+ * Default constructor, which will construct the default JSON-handling
+ * {@link TokenStreamFactory} as necessary and all other unmodified
+ * default settings, and no additional registered modules.
*/
- protected ObjectMapper(ObjectMapper src)
- {
- _jsonFactory = src._jsonFactory.copy();
- _jsonFactory.setCodec(this);
- _subtypeResolver = src._subtypeResolver;
- _typeFactory = src._typeFactory;
- _injectableValues = src._injectableValues;
- _configOverrides = src._configOverrides.copy();
- _mixIns = src._mixIns.copy();
-
- RootNameLookup rootNames = new RootNameLookup();
- _serializationConfig = new SerializationConfig(src._serializationConfig,
- _mixIns, rootNames, _configOverrides);
- _deserializationConfig = new DeserializationConfig(src._deserializationConfig,
- _mixIns, rootNames, _configOverrides);
- _serializerProvider = src._serializerProvider.copy();
- _deserializationContext = src._deserializationContext.copy();
-
- // Default serializer factory is stateless, can just assign
- _serializerFactory = src._serializerFactory;
-
- // as per [databind#922], [databind#1078] make sure to copy registered modules as appropriate
- Set reg = src._registeredModuleTypes;
- if (reg == null) {
- _registeredModuleTypes = null;
- } else {
- _registeredModuleTypes = new LinkedHashSet(reg);
- }
+ public ObjectMapper() {
+ this(new PrivateBuilder(new JsonFactory()));
}
/**
- * Constructs instance that uses specified {@link JsonFactory}
+ * Constructs instance that uses specified {@link TokenStreamFactory}
* for constructing necessary {@link JsonParser}s and/or
- * {@link JsonGenerator}s, and uses given providers for accessing
- * serializers and deserializers.
- *
- * @param jf JsonFactory to use: if null, a new {@link MappingJsonFactory} will be constructed
- * @param sp SerializerProvider to use: if null, a {@link SerializerProvider} will be constructed
- * @param dc Blueprint deserialization context instance to use for creating
- * actual context objects; if null, will construct standard
- * {@link DeserializationContext}
- */
- public ObjectMapper(JsonFactory jf,
- DefaultSerializerProvider sp, DefaultDeserializationContext dc)
- {
- /* 02-Mar-2009, tatu: Important: we MUST default to using
- * the mapping factory, otherwise tree serialization will
- * have problems with POJONodes.
- * 03-Jan-2010, tatu: and obviously we also must pass 'this',
- * to create actual linking.
- */
- if (jf == null) {
- _jsonFactory = new MappingJsonFactory(this);
- } else {
- _jsonFactory = jf;
- if (jf.getCodec() == null) { // as per [JACKSON-741]
- _jsonFactory.setCodec(this);
- }
- }
- _subtypeResolver = new StdSubtypeResolver();
- RootNameLookup rootNames = new RootNameLookup();
- // and default type factory is shared one
- _typeFactory = TypeFactory.defaultInstance();
-
- SimpleMixInResolver mixins = new SimpleMixInResolver(null);
- _mixIns = mixins;
- BaseSettings base = DEFAULT_BASE.withClassIntrospector(defaultClassIntrospector());
- _configOverrides = new ConfigOverrides();
- _serializationConfig = new SerializationConfig(base,
- _subtypeResolver, mixins, rootNames, _configOverrides);
- _deserializationConfig = new DeserializationConfig(base,
- _subtypeResolver, mixins, rootNames, _configOverrides);
-
- // Some overrides we may need
- final boolean needOrder = _jsonFactory.requiresPropertyOrdering();
- if (needOrder ^ _serializationConfig.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)) {
- configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, needOrder);
- }
-
- _serializerProvider = (sp == null) ? new DefaultSerializerProvider.Impl() : sp;
- _deserializationContext = (dc == null) ?
- new DefaultDeserializationContext.Impl(BeanDeserializerFactory.instance) : dc;
-
- // Default serializer factory is stateless, can just assign
- _serializerFactory = BeanSerializerFactory.instance;
- }
-
- /**
- * Overridable helper method used to construct default {@link ClassIntrospector}
- * to use.
- *
- * @since 2.5
+ * {@link JsonGenerator}s, but without registering additional modules.
*/
- protected ClassIntrospector defaultClassIntrospector() {
- return new BasicClassIntrospector();
+ public ObjectMapper(TokenStreamFactory streamFactory) {
+ this(new PrivateBuilder(streamFactory));
}
/*
- /**********************************************************
- /* Methods sub-classes MUST override
- /**********************************************************
- */
-
- /**
- * Method for creating a new {@link ObjectMapper} instance that
- * has same initial configuration as this instance. Note that this
- * also requires making a copy of the underlying {@link JsonFactory}
- * instance.
- *
- * Method is typically
- * used when multiple, differently configured mappers are needed.
- * Although configuration is shared, cached serializers and deserializers
- * are NOT shared, which means that the new instance may be re-configured
- * before use; meaning that it behaves the same way as if an instance
- * was constructed from scratch.
- *
- * @since 2.1
+ /**********************************************************************
+ /* Life-cycle: builder-style construction
+ /**********************************************************************
*/
- public ObjectMapper copy() {
- _checkInvalidCopy(ObjectMapper.class);
- return new ObjectMapper(this);
- }
/**
- * @since 2.1
+ * Constructor usually called either by {@link MapperBuilder#build} or
+ * by sub-class constructor: will get all the settings through passed-in
+ * builder, including registration of any modules added to builder.
*/
- protected void _checkInvalidCopy(Class> exp)
+ protected ObjectMapper(MapperBuilder,?> builder)
{
- if (getClass() != exp) {
- // 10-Nov-2016, tatu: could almost use `ClassUtil.verifyMustOverride()` but not quite
- throw new IllegalStateException("Failed copy(): "+getClass().getName()
- +" (version: "+version()+") does not override copy(); it has to");
+ // First things first: finalize building process. Saved state
+ // consists of snapshots and is safe to keep references to; used
+ // for rebuild()ing mapper instances
+
+ _savedBuilderState = builder.saveStateApplyModules();
+
+ // But we will ALSO need to take snapshot of anything builder has,
+ // in case caller keeps on tweaking with builder. So rules are the
+ // as with above call, or when creating new builder for rebuild()ing
+
+ // General framework factories
+ _streamFactory = builder.streamFactory();
+ final ConfigOverrides configOverrides;
+ {
+ // bit tricky as we do NOT want to expose simple accessors (to a mutable thing)
+ final AtomicReference ref = new AtomicReference<>();
+ builder.withAllConfigOverrides(overrides -> ref.set(overrides));
+ configOverrides = Snapshottable.takeSnapshot(ref.get());
}
- }
- /*
- /**********************************************************
- /* Methods sub-classes MUST override if providing custom
- /* ObjectReader/ObjectWriter implementations
- /**********************************************************
- */
-
- /**
- * Factory method sub-classes must override, to produce {@link ObjectReader}
- * instances of proper sub-type
- *
- * @since 2.5
- */
- protected ObjectReader _newReader(DeserializationConfig config) {
- return new ObjectReader(this, config);
- }
+ // Handlers, introspection
+ _typeFactory = Snapshottable.takeSnapshot(builder.typeFactory());
+ ClassIntrospector classIntr = builder.classIntrospector().forMapper(this);
+ SubtypeResolver subtypeResolver = Snapshottable.takeSnapshot(builder.subtypeResolver());
+ MixInHandler mixIns = (MixInHandler) Snapshottable.takeSnapshot(builder.mixInHandler());
+ // NOTE: TypeResolverProvider apparently ok without snapshot, hence config objects fetch
+ // it directly from MapperBuilder, not passed by us.
- /**
- * Factory method sub-classes must override, to produce {@link ObjectReader}
- * instances of proper sub-type
- *
- * @since 2.5
- */
- protected ObjectReader _newReader(DeserializationConfig config,
- JavaType valueType, Object valueToUpdate,
- FormatSchema schema, InjectableValues injectableValues) {
- return new ObjectReader(this, config, valueType, valueToUpdate, schema, injectableValues);
+ // Serialization factories
+ _serializationContexts = builder.serializationContexts()
+ .forMapper(this, _streamFactory, builder.serializerFactory());
+
+ // Deserialization factories
+
+ _deserializationContexts = builder.deserializationContexts()
+ .forMapper(this, _streamFactory, builder.deserializerFactory());
+ _injectableValues = Snapshottable.takeSnapshot(builder.injectableValues());
+
+ // And then finalize serialization/deserialization Config containers
+
+ RootNameLookup rootNames = new RootNameLookup();
+ FilterProvider filterProvider = Snapshottable.takeSnapshot(builder.filterProvider());
+ _deserializationConfig = builder.buildDeserializationConfig(configOverrides,
+ mixIns, _typeFactory, classIntr, subtypeResolver,
+ rootNames);
+ _serializationConfig = builder.buildSerializationConfig(configOverrides,
+ mixIns, _typeFactory, classIntr, subtypeResolver,
+ rootNames, filterProvider);
}
/**
- * Factory method sub-classes must override, to produce {@link ObjectWriter}
- * instances of proper sub-type
- *
- * @since 2.5
+ * Method for creating a new {@link MapperBuilder} for constructing differently configured
+ * {@link ObjectMapper} instance, starting with current configuration including base settings
+ * and registered modules.
+ *
+ * @since 3.0
*/
- protected ObjectWriter _newWriter(SerializationConfig config) {
- return new ObjectWriter(this, config);
+ @SuppressWarnings("unchecked")
+ public > MapperBuilder rebuild() {
+ // 27-Feb-2018, tatu: since we still have problem with `ObjectMapper` being both API
+ // and implementation for JSON, need more checking here
+ ClassUtil.verifyMustOverride(ObjectMapper.class, this, "rebuild");
+ return (MapperBuilder) new PrivateBuilder(_savedBuilderState);
}
- /**
- * Factory method sub-classes must override, to produce {@link ObjectWriter}
- * instances of proper sub-type
- *
- * @since 2.5
+ /*
+ /**********************************************************************
+ /* Life-cycle: JDK serialization support
+ /**********************************************************************
*/
- protected ObjectWriter _newWriter(SerializationConfig config, FormatSchema schema) {
- return new ObjectWriter(this, config, schema);
+
+ // Logic here is simple: instead of serializing mapper via its contents,
+ // we have pre-packaged `MapperBuilderState` in a way that makes serialization
+ // easier, and we go with that.
+ // But note that return direction has to be supported, then, by that state object
+ // and NOT anything in here.
+ protected Object writeReplace() {
+ return _savedBuilderState;
}
-
- /**
- * Factory method sub-classes must override, to produce {@link ObjectWriter}
- * instances of proper sub-type
- *
- * @since 2.5
- */
- protected ObjectWriter _newWriter(SerializationConfig config,
- JavaType rootType, PrettyPrinter pp) {
- return new ObjectWriter(this, config, rootType, pp);
+
+ // Just as a sanity check verify there is no attempt at directly instantiating mapper here
+ protected Object readResolve() {
+ throw new IllegalStateException("Should never deserialize `"+getClass().getName()+"` directly");
}
/*
- /**********************************************************
+ /**********************************************************************
/* Versioned impl
- /**********************************************************
+ /**********************************************************************
*/
-
+
/**
* Method that will return version information stored in and read from jar
* that contains this class.
@@ -704,1238 +396,110 @@ public Version version() {
return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION;
}
- /*
- /**********************************************************
- /* Module registration, discovery
- /**********************************************************
- */
-
- /**
- * Method for registering a module that can extend functionality
- * provided by this mapper; for example, by adding providers for
- * custom serializers and deserializers.
- *
- * @param module Module to register
- */
- public ObjectMapper registerModule(Module module)
- {
- if (isEnabled(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS)) {
- Object typeId = module.getTypeId();
- if (typeId != null) {
- if (_registeredModuleTypes == null) {
- // plus let's keep them in order too, easier to debug or expose
- // in registration order if that matter
- _registeredModuleTypes = new LinkedHashSet();
- }
- // try adding; if already had it, should skip
- if (!_registeredModuleTypes.add(typeId)) {
- return this;
- }
- }
- }
-
- /* Let's ensure we have access to name and version information,
- * even if we do not have immediate use for either. This way we know
- * that they will be available from beginning
- */
- String name = module.getModuleName();
- if (name == null) {
- throw new IllegalArgumentException("Module without defined name");
- }
- Version version = module.version();
- if (version == null) {
- throw new IllegalArgumentException("Module without defined version");
- }
-
- // And then call registration
- module.setupModule(new Module.SetupContext()
- {
- // // // Accessors
-
- @Override
- public Version getMapperVersion() {
- return version();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public C getOwner() {
- // why do we need the cast here?!?
- return (C) ObjectMapper.this;
- }
-
- @Override
- public TypeFactory getTypeFactory() {
- return _typeFactory;
- }
-
- @Override
- public boolean isEnabled(MapperFeature f) {
- return ObjectMapper.this.isEnabled(f);
- }
-
- @Override
- public boolean isEnabled(DeserializationFeature f) {
- return ObjectMapper.this.isEnabled(f);
- }
-
- @Override
- public boolean isEnabled(SerializationFeature f) {
- return ObjectMapper.this.isEnabled(f);
- }
-
- @Override
- public boolean isEnabled(JsonFactory.Feature f) {
- return ObjectMapper.this.isEnabled(f);
- }
-
- @Override
- public boolean isEnabled(JsonParser.Feature f) {
- return ObjectMapper.this.isEnabled(f);
- }
-
- @Override
- public boolean isEnabled(JsonGenerator.Feature f) {
- return ObjectMapper.this.isEnabled(f);
- }
-
- // // // Mutant accessors
-
- @Override
- public MutableConfigOverride configOverride(Class> type) {
- return ObjectMapper.this.configOverride(type);
- }
-
- // // // Methods for registering handlers: deserializers
-
- @Override
- public void addDeserializers(Deserializers d) {
- DeserializerFactory df = _deserializationContext._factory.withAdditionalDeserializers(d);
- _deserializationContext = _deserializationContext.with(df);
- }
-
- @Override
- public void addKeyDeserializers(KeyDeserializers d) {
- DeserializerFactory df = _deserializationContext._factory.withAdditionalKeyDeserializers(d);
- _deserializationContext = _deserializationContext.with(df);
- }
-
- @Override
- public void addBeanDeserializerModifier(BeanDeserializerModifier modifier) {
- DeserializerFactory df = _deserializationContext._factory.withDeserializerModifier(modifier);
- _deserializationContext = _deserializationContext.with(df);
- }
-
- // // // Methods for registering handlers: serializers
-
- @Override
- public void addSerializers(Serializers s) {
- _serializerFactory = _serializerFactory.withAdditionalSerializers(s);
- }
-
- @Override
- public void addKeySerializers(Serializers s) {
- _serializerFactory = _serializerFactory.withAdditionalKeySerializers(s);
- }
-
- @Override
- public void addBeanSerializerModifier(BeanSerializerModifier modifier) {
- _serializerFactory = _serializerFactory.withSerializerModifier(modifier);
- }
-
- // // // Methods for registering handlers: other
-
- @Override
- public void addAbstractTypeResolver(AbstractTypeResolver resolver) {
- DeserializerFactory df = _deserializationContext._factory.withAbstractTypeResolver(resolver);
- _deserializationContext = _deserializationContext.with(df);
- }
-
- @Override
- public void addTypeModifier(TypeModifier modifier) {
- TypeFactory f = _typeFactory;
- f = f.withModifier(modifier);
- setTypeFactory(f);
- }
-
- @Override
- public void addValueInstantiators(ValueInstantiators instantiators) {
- DeserializerFactory df = _deserializationContext._factory.withValueInstantiators(instantiators);
- _deserializationContext = _deserializationContext.with(df);
- }
-
- @Override
- public void setClassIntrospector(ClassIntrospector ci) {
- _deserializationConfig = _deserializationConfig.with(ci);
- _serializationConfig = _serializationConfig.with(ci);
- }
-
- @Override
- public void insertAnnotationIntrospector(AnnotationIntrospector ai) {
- _deserializationConfig = _deserializationConfig.withInsertedAnnotationIntrospector(ai);
- _serializationConfig = _serializationConfig.withInsertedAnnotationIntrospector(ai);
- }
-
- @Override
- public void appendAnnotationIntrospector(AnnotationIntrospector ai) {
- _deserializationConfig = _deserializationConfig.withAppendedAnnotationIntrospector(ai);
- _serializationConfig = _serializationConfig.withAppendedAnnotationIntrospector(ai);
- }
-
- @Override
- public void registerSubtypes(Class>... subtypes) {
- ObjectMapper.this.registerSubtypes(subtypes);
- }
-
- @Override
- public void registerSubtypes(NamedType... subtypes) {
- ObjectMapper.this.registerSubtypes(subtypes);
- }
-
- @Override
- public void registerSubtypes(Collection> subtypes) {
- ObjectMapper.this.registerSubtypes(subtypes);
- }
-
- @Override
- public void setMixInAnnotations(Class> target, Class> mixinSource) {
- addMixIn(target, mixinSource);
- }
-
- @Override
- public void addDeserializationProblemHandler(DeserializationProblemHandler handler) {
- addHandler(handler);
- }
-
- @Override
- public void setNamingStrategy(PropertyNamingStrategy naming) {
- setPropertyNamingStrategy(naming);
- }
- });
- return this;
- }
-
- /**
- * Convenience method for registering specified modules in order;
- * functionally equivalent to:
- *
- * for (Module module : modules) {
- * registerModule(module);
- * }
- *
- *
- * @since 2.2
- */
- public ObjectMapper registerModules(Module... modules)
- {
- for (Module module : modules) {
- registerModule(module);
- }
- return this;
- }
-
- /**
- * Convenience method for registering specified modules in order;
- * functionally equivalent to:
- *
- * for (Module module : modules) {
- * registerModule(module);
- * }
- *
- *
- * @since 2.2
- */
- public ObjectMapper registerModules(Iterable extends Module> modules)
- {
- for (Module module : modules) {
- registerModule(module);
- }
- return this;
- }
-
- /**
- * The set of {@link Module} typeIds that are registered in this
- * ObjectMapper. By default the typeId for a module is it's full
- * class name (see {@link Module#getTypeId()}).
- *
- * @since 2.9.6
- */
- public Set getRegisteredModuleIds()
- {
- return Collections.unmodifiableSet(_registeredModuleTypes);
- }
-
- /**
- * Method for locating available methods, using JDK {@link ServiceLoader}
- * facility, along with module-provided SPI.
- *
- * Note that method does not do any caching, so calls should be considered
- * potentially expensive.
- *
- * @since 2.2
- */
- public static List findModules() {
- return findModules(null);
- }
-
- /**
- * Method for locating available methods, using JDK {@link ServiceLoader}
- * facility, along with module-provided SPI.
- *
- * Note that method does not do any caching, so calls should be considered
- * potentially expensive.
- *
- * @since 2.2
- */
- public static List findModules(ClassLoader classLoader)
- {
- ArrayList modules = new ArrayList();
- ServiceLoader loader = secureGetServiceLoader(Module.class, classLoader);
- for (Module module : loader) {
- modules.add(module);
- }
- return modules;
- }
-
- private static ServiceLoader secureGetServiceLoader(final Class clazz, final ClassLoader classLoader) {
- final SecurityManager sm = System.getSecurityManager();
- if (sm == null) {
- return (classLoader == null) ?
- ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
- }
- return AccessController.doPrivileged(new PrivilegedAction>() {
- @Override
- public ServiceLoader run() {
- return (classLoader == null) ?
- ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
- }
- });
- }
-
- /**
- * Convenience method that is functionally equivalent to:
- *
- * mapper.registerModules(mapper.findModules());
- *
- *
- * As with {@link #findModules()}, no caching is done for modules, so care
- * needs to be taken to either create and share a single mapper instance;
- * or to cache introspected set of modules.
- *
- * @since 2.2
- */
- public ObjectMapper findAndRegisterModules() {
- return registerModules(findModules());
- }
-
- /*
- /**********************************************************
- /* Configuration: main config object access
- /**********************************************************
- */
-
- /**
- * Method that returns the shared default {@link SerializationConfig}
- * object that defines configuration settings for serialization.
- *
- * Note that since instances are immutable, you can NOT change settings
- * by accessing an instance and calling methods: this will simply create
- * new instance of config object.
- */
- public SerializationConfig getSerializationConfig() {
- return _serializationConfig;
- }
-
- /**
- * Method that returns
- * the shared default {@link DeserializationConfig} object
- * that defines configuration settings for deserialization.
- *
- * Note that since instances are immutable, you can NOT change settings
- * by accessing an instance and calling methods: this will simply create
- * new instance of config object.
- */
- public DeserializationConfig getDeserializationConfig() {
- return _deserializationConfig;
- }
-
- /**
- * Method for getting current {@link DeserializationContext}.
- *
- * Note that since instances are immutable, you can NOT change settings
- * by accessing an instance and calling methods: this will simply create
- * new instance of context object.
- */
- public DeserializationContext getDeserializationContext() {
- return _deserializationContext;
- }
-
- /*
- /**********************************************************
- /* Configuration: ser/deser factory, provider access
- /**********************************************************
- */
-
- /**
- * Method for setting specific {@link SerializerFactory} to use
- * for constructing (bean) serializers.
- */
- public ObjectMapper setSerializerFactory(SerializerFactory f) {
- _serializerFactory = f;
- return this;
- }
-
- /**
- * Method for getting current {@link SerializerFactory}.
- *
- * Note that since instances are immutable, you can NOT change settings
- * by accessing an instance and calling methods: this will simply create
- * new instance of factory object.
- */
- public SerializerFactory getSerializerFactory() {
- return _serializerFactory;
- }
-
- /**
- * Method for setting "blueprint" {@link SerializerProvider} instance
- * to use as the base for actual provider instances to use for handling
- * caching of {@link JsonSerializer} instances.
- */
- public ObjectMapper setSerializerProvider(DefaultSerializerProvider p) {
- _serializerProvider = p;
- return this;
- }
-
- /**
- * Accessor for the "blueprint" (or, factory) instance, from which instances
- * are created by calling {@link DefaultSerializerProvider#createInstance}.
- * Note that returned instance cannot be directly used as it is not properly
- * configured: to get a properly configured instance to call, use
- * {@link #getSerializerProviderInstance()} instead.
- */
- public SerializerProvider getSerializerProvider() {
- return _serializerProvider;
- }
-
- /**
- * Accessor for constructing and returning a {@link SerializerProvider}
- * instance that may be used for accessing serializers. This is same as
- * calling {@link #getSerializerProvider}, and calling createInstance
- * on it.
- *
- * @since 2.7
- */
- public SerializerProvider getSerializerProviderInstance() {
- return _serializerProvider(_serializationConfig);
- }
-
- /*
- /**********************************************************
- /* Configuration: mix-in annotations
- /**********************************************************
- */
-
- /**
- * Method to use for defining mix-in annotations to use for augmenting
- * annotations that processable (serializable / deserializable)
- * classes have.
- * Mixing in is done when introspecting class annotations and properties.
- * Map passed contains keys that are target classes (ones to augment
- * with new annotation overrides), and values that are source classes
- * (have annotations to use for augmentation).
- * Annotations from source classes (and their supertypes)
- * will override
- * annotations that target classes (and their super-types) have.
- *
- * Note that this method will CLEAR any previously defined mix-ins
- * for this mapper.
- *
- * @since 2.5
- */
- public ObjectMapper setMixIns(Map, Class>> sourceMixins)
- {
- // NOTE: does NOT change possible externally configured resolver, just local defs
- _mixIns.setLocalDefinitions(sourceMixins);
- return this;
- }
-
- /**
- * Method to use for adding mix-in annotations to use for augmenting
- * specified class or interface. All annotations from
- * mixinSource
are taken to override annotations
- * that target
(or its supertypes) has.
- *
- * @param target Class (or interface) whose annotations to effectively override
- * @param mixinSource Class (or interface) whose annotations are to
- * be "added" to target's annotations, overriding as necessary
- *
- * @since 2.5
- */
- public ObjectMapper addMixIn(Class> target, Class> mixinSource)
- {
- _mixIns.addLocalDefinition(target, mixinSource);
- return this;
- }
-
- /**
- * Method that can be called to specify given resolver for locating
- * mix-in classes to use, overriding directly added mappings.
- * Note that direct mappings are not cleared, but they are only applied
- * if resolver does not provide mix-in matches.
- *
- * @since 2.6
- */
- public ObjectMapper setMixInResolver(ClassIntrospector.MixInResolver resolver)
- {
- SimpleMixInResolver r = _mixIns.withOverrides(resolver);
- if (r != _mixIns) {
- _mixIns = r;
- _deserializationConfig = new DeserializationConfig(_deserializationConfig, r);
- _serializationConfig = new SerializationConfig(_serializationConfig, r);
- }
- return this;
- }
-
- public Class> findMixInClassFor(Class> cls) {
- return _mixIns.findMixInClassFor(cls);
- }
-
- // For testing only:
- public int mixInCount() {
- return _mixIns.localSize();
- }
-
- /**
- * @deprecated Since 2.5: replaced by a fluent form of the method; {@link #setMixIns}.
- */
- @Deprecated
- public void setMixInAnnotations(Map, Class>> sourceMixins) {
- setMixIns(sourceMixins);
- }
-
- /**
- * @deprecated Since 2.5: replaced by a fluent form of the method; {@link #addMixIn(Class, Class)}.
- */
- @Deprecated
- public final void addMixInAnnotations(Class> target, Class> mixinSource) {
- addMixIn(target, mixinSource);
- }
-
- /*
- /**********************************************************
- /* Configuration, introspection
- /**********************************************************
- */
-
- /**
- * Method for accessing currently configured visibility checker;
- * object used for determining whether given property element
- * (method, field, constructor) can be auto-detected or not.
- */
- public VisibilityChecker> getVisibilityChecker() {
- return _serializationConfig.getDefaultVisibilityChecker();
- }
-
- /**
- * Method for setting currently configured default {@link VisibilityChecker},
- * object used for determining whether given property element
- * (method, field, constructor) can be auto-detected or not.
- * This default checker is used as the base visibility:
- * per-class overrides (both via annotations and per-type config overrides)
- * can further change these settings.
- *
- * @since 2.6
- */
- public ObjectMapper setVisibility(VisibilityChecker> vc) {
- _configOverrides.setDefaultVisibility(vc);
- return this;
- }
-
- /**
- * Convenience method that allows changing configuration for
- * underlying {@link VisibilityChecker}s, to change details of what kinds of
- * properties are auto-detected.
- * Basically short cut for doing:
- *
- * mapper.setVisibilityChecker(
- * mapper.getVisibilityChecker().withVisibility(forMethod, visibility)
- * );
- *
- * one common use case would be to do:
- *
- * mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
- *
- * which would make all member fields serializable without further annotations,
- * instead of just public fields (default setting).
- *
- * @param forMethod Type of property descriptor affected (field, getter/isGetter,
- * setter, creator)
- * @param visibility Minimum visibility to require for the property descriptors of type
- *
- * @return Modified mapper instance (that is, "this"), to allow chaining
- * of configuration calls
- */
- public ObjectMapper setVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility)
- {
- VisibilityChecker> vc = _configOverrides.getDefaultVisibility();
- vc = vc.withVisibility(forMethod, visibility);
- _configOverrides.setDefaultVisibility(vc);
- return this;
- }
-
- /**
- * Method for accessing subtype resolver in use.
- */
- public SubtypeResolver getSubtypeResolver() {
- return _subtypeResolver;
- }
-
- /**
- * Method for setting custom subtype resolver to use.
- */
- public ObjectMapper setSubtypeResolver(SubtypeResolver str) {
- _subtypeResolver = str;
- _deserializationConfig = _deserializationConfig.with(str);
- _serializationConfig = _serializationConfig.with(str);
- return this;
- }
-
- /**
- * Method for setting {@link AnnotationIntrospector} used by this
- * mapper instance for both serialization and deserialization.
- * Note that doing this will replace the current introspector, which
- * may lead to unavailability of core Jackson annotations.
- * If you want to combine handling of multiple introspectors,
- * have a look at {@link com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair}.
- *
- * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair
- */
- public ObjectMapper setAnnotationIntrospector(AnnotationIntrospector ai) {
- _serializationConfig = _serializationConfig.with(ai);
- _deserializationConfig = _deserializationConfig.with(ai);
- return this;
- }
-
- /**
- * Method for changing {@link AnnotationIntrospector} instances used
- * by this mapper instance for serialization and deserialization,
- * specifying them separately so that different introspection can be
- * used for different aspects
- *
- * @since 2.1
- *
- * @param serializerAI {@link AnnotationIntrospector} to use for configuring
- * serialization
- * @param deserializerAI {@link AnnotationIntrospector} to use for configuring
- * deserialization
- *
- * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair
- */
- public ObjectMapper setAnnotationIntrospectors(AnnotationIntrospector serializerAI,
- AnnotationIntrospector deserializerAI) {
- _serializationConfig = _serializationConfig.with(serializerAI);
- _deserializationConfig = _deserializationConfig.with(deserializerAI);
- return this;
- }
-
- /**
- * Method for setting custom property naming strategy to use.
- */
- public ObjectMapper setPropertyNamingStrategy(PropertyNamingStrategy s) {
- _serializationConfig = _serializationConfig.with(s);
- _deserializationConfig = _deserializationConfig.with(s);
- return this;
- }
-
- /**
- * @since 2.5
- */
- public PropertyNamingStrategy getPropertyNamingStrategy() {
- // arbitrary choice but let's do:
- return _serializationConfig.getPropertyNamingStrategy();
- }
-
- /**
- * Method for specifying {@link PrettyPrinter} to use when "default pretty-printing"
- * is enabled (by enabling {@link SerializationFeature#INDENT_OUTPUT})
- *
- * @param pp Pretty printer to use by default.
- *
- * @return This mapper, useful for call-chaining
- *
- * @since 2.6
- */
- public ObjectMapper setDefaultPrettyPrinter(PrettyPrinter pp) {
- _serializationConfig = _serializationConfig.withDefaultPrettyPrinter(pp);
- return this;
- }
-
- /**
- * @deprecated Since 2.6 use {@link #setVisibility(VisibilityChecker)} instead.
- */
- @Deprecated
- public void setVisibilityChecker(VisibilityChecker> vc) {
- setVisibility(vc);
- }
-
- /*
- /**********************************************************
- /* Configuration: global-default/per-type override settings
- /**********************************************************
- */
-
- /**
- * Convenience method, equivalent to calling:
- *
- * setPropertyInclusion(JsonInclude.Value.construct(incl, incl));
- *
- *
- * NOTE: behavior differs slightly from 2.8, where second argument was
- * implied to be JsonInclude.Include.ALWAYS
.
- */
- public ObjectMapper setSerializationInclusion(JsonInclude.Include incl) {
- setPropertyInclusion(JsonInclude.Value.construct(incl, incl));
- return this;
- }
-
- /**
- * @since 2.7
- * @deprecated Since 2.9 use {@link #setDefaultPropertyInclusion}
- */
- @Deprecated
- public ObjectMapper setPropertyInclusion(JsonInclude.Value incl) {
- return setDefaultPropertyInclusion(incl);
- }
-
- /**
- * Method for setting default POJO property inclusion strategy for serialization,
- * applied for all properties for which there are no per-type or per-property
- * overrides (via annotations or config overrides).
- *
- * @since 2.9 (basically rename of setPropertyInclusion
)
- */
- public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Value incl) {
- _configOverrides.setDefaultInclusion(incl);
- return this;
- }
-
- /**
- * Short-cut for:
- *
- * setDefaultPropertyInclusion(JsonInclude.Value.construct(incl, incl));
- *
- *
- * @since 2.9 (basically rename of setPropertyInclusion
)
- */
- public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Include incl) {
- _configOverrides.setDefaultInclusion(JsonInclude.Value.construct(incl, incl));
- return this;
- }
-
- /**
- * Method for setting default Setter configuration, regarding things like
- * merging, null-handling; used for properties for which there are
- * no per-type or per-property overrides (via annotations or config overrides).
- *
- * @since 2.9
- */
- public ObjectMapper setDefaultSetterInfo(JsonSetter.Value v) {
- _configOverrides.setDefaultSetterInfo(v);
- return this;
- }
-
- /**
- * Method for setting auto-detection visibility definition
- * defaults, which are in effect unless overridden by
- * annotations (like JsonAutoDetect
) or per-type
- * visibility overrides.
- *
- * @since 2.9
- */
- public ObjectMapper setDefaultVisibility(JsonAutoDetect.Value vis) {
- _configOverrides.setDefaultVisibility(VisibilityChecker.Std.construct(vis));
- return this;
- }
-
- /**
- * Method for setting default Setter configuration, regarding things like
- * merging, null-handling; used for properties for which there are
- * no per-type or per-property overrides (via annotations or config overrides).
- *
- * @since 2.9
- */
- public ObjectMapper setDefaultMergeable(Boolean b) {
- _configOverrides.setDefaultMergeable(b);
- return this;
- }
-
- /*
- /**********************************************************
- /* Type information configuration
- /**********************************************************
- */
-
- /**
- * Convenience method that is equivalent to calling
- *
- * enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
- *
- *
- * NOTE: use of Default Typing can be a potential security risk if incoming
- * content comes from untrusted sources, and it is recommended that this
- * is either not done, or, if enabled, use {@link #setDefaultTyping}
- * passing a custom {@link TypeResolverBuilder} implementation that white-lists
- * legal types to use.
- */
- public ObjectMapper enableDefaultTyping() {
- return enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
- }
-
- /**
- * Convenience method that is equivalent to calling
- *
- * enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
- *
- *
- * NOTE: use of Default Typing can be a potential security risk if incoming
- * content comes from untrusted sources, and it is recommended that this
- * is either not done, or, if enabled, use {@link #setDefaultTyping}
- * passing a custom {@link TypeResolverBuilder} implementation that white-lists
- * legal types to use.
- */
- public ObjectMapper enableDefaultTyping(DefaultTyping dti) {
- return enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
- }
-
- /**
- * Method for enabling automatic inclusion of type information, needed
- * for proper deserialization of polymorphic types (unless types
- * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
- *
- * NOTE: use of JsonTypeInfo.As#EXTERNAL_PROPERTY
NOT SUPPORTED ;
- * and attempts of do so will throw an {@link IllegalArgumentException} to make
- * this limitation explicit.
- *
- * NOTE: use of Default Typing can be a potential security risk if incoming
- * content comes from untrusted sources, and it is recommended that this
- * is either not done, or, if enabled, use {@link #setDefaultTyping}
- * passing a custom {@link TypeResolverBuilder} implementation that white-lists
- * legal types to use.
- *
- * @param applicability Defines kinds of types for which additional type information
- * is added; see {@link DefaultTyping} for more information.
- */
- public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs)
- {
- /* 18-Sep-2014, tatu: Let's add explicit check to ensure no one tries to
- * use "As.EXTERNAL_PROPERTY", since that will not work (with 2.5+)
- */
- if (includeAs == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
- throw new IllegalArgumentException("Cannot use includeAs of "+includeAs);
- }
-
- TypeResolverBuilder> typer = _constructDefaultTypeResolverBuilder(applicability);
- // we'll always use full class name, when using defaulting
- typer = typer.init(JsonTypeInfo.Id.CLASS, null);
- typer = typer.inclusion(includeAs);
- return setDefaultTyping(typer);
- }
-
- /**
- * Method for enabling automatic inclusion of type information -- needed
- * for proper deserialization of polymorphic types (unless types
- * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) --
- * using "As.PROPERTY" inclusion mechanism and specified property name
- * to use for inclusion (default being "@class" since default type information
- * always uses class name as type identifier)
- *
- * NOTE: use of Default Typing can be a potential security risk if incoming
- * content comes from untrusted sources, and it is recommended that this
- * is either not done, or, if enabled, use {@link #setDefaultTyping}
- * passing a custom {@link TypeResolverBuilder} implementation that white-lists
- * legal types to use.
- */
- public ObjectMapper enableDefaultTypingAsProperty(DefaultTyping applicability, String propertyName)
- {
- TypeResolverBuilder> typer = _constructDefaultTypeResolverBuilder(applicability);
- // we'll always use full class name, when using defaulting
- typer = typer.init(JsonTypeInfo.Id.CLASS, null);
- typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
- typer = typer.typeProperty(propertyName);
- return setDefaultTyping(typer);
- }
-
- /**
- * Method for disabling automatic inclusion of type information; if so, only
- * explicitly annotated types (ones with
- * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have
- * additional embedded type information.
- */
- public ObjectMapper disableDefaultTyping() {
- return setDefaultTyping(null);
- }
-
- /**
- * Method for enabling automatic inclusion of type information, using
- * specified handler object for determining which types this affects,
- * as well as details of how information is embedded.
- *
- * NOTE: use of Default Typing can be a potential security risk if incoming
- * content comes from untrusted sources, so care should be taken to use
- * a {@link TypeResolverBuilder} that can limit allowed classes to
- * deserialize.
- *
- * @param typer Type information inclusion handler
- */
- public ObjectMapper setDefaultTyping(TypeResolverBuilder> typer) {
- _deserializationConfig = _deserializationConfig.with(typer);
- _serializationConfig = _serializationConfig.with(typer);
- return this;
- }
-
- /**
- * Method for registering specified class as a subtype, so that
- * typename-based resolution can link supertypes to subtypes
- * (as an alternative to using annotations).
- * Type for given class is determined from appropriate annotation;
- * or if missing, default name (unqualified class name)
- */
- public void registerSubtypes(Class>... classes) {
- getSubtypeResolver().registerSubtypes(classes);
- }
-
- /**
- * Method for registering specified class as a subtype, so that
- * typename-based resolution can link supertypes to subtypes
- * (as an alternative to using annotations).
- * Name may be provided as part of argument, but if not will
- * be based on annotations or use default name (unqualified
- * class name).
- */
- public void registerSubtypes(NamedType... types) {
- getSubtypeResolver().registerSubtypes(types);
- }
-
- /**
- * @since 2.9
- */
- public void registerSubtypes(Collection> subtypes) {
- getSubtypeResolver().registerSubtypes(subtypes);
- }
-
- /*
- /**********************************************************
- /* Configuration, basic type handling
- /**********************************************************
- */
-
- /**
- * Accessor for getting a mutable configuration override object for
- * given type, needed to add or change per-type overrides applied
- * to properties of given type.
- * Usage is through returned object by colling "setter" methods, which
- * directly modify override object and take effect directly.
- * For example you can do
- *
- * mapper.configOverride(java.util.Date.class)
- * .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
- *
- * to change the default format to use for properties of type
- * {@link java.util.Date} (possibly further overridden by per-property
- * annotations)
- *
- * @since 2.8
- */
- public MutableConfigOverride configOverride(Class> type) {
- return _configOverrides.findOrCreateOverride(type);
- }
-
- /*
- /**********************************************************
- /* Configuration, basic type handling
- /**********************************************************
- */
-
- /**
- * Accessor for getting currently configured {@link TypeFactory} instance.
- */
- public TypeFactory getTypeFactory() {
- return _typeFactory;
- }
-
- /**
- * Method that can be used to override {@link TypeFactory} instance
- * used by this mapper.
- *
- * Note: will also set {@link TypeFactory} that deserialization and
- * serialization config objects use.
- */
- public ObjectMapper setTypeFactory(TypeFactory f)
- {
- _typeFactory = f;
- _deserializationConfig = _deserializationConfig.with(f);
- _serializationConfig = _serializationConfig.with(f);
- return this;
- }
-
- /**
- * Convenience method for constructing {@link JavaType} out of given
- * type (typically java.lang.Class
), but without explicit
- * context.
- */
- public JavaType constructType(Type t) {
- return _typeFactory.constructType(t);
- }
-
- /*
- /**********************************************************
- /* Configuration, deserialization
- /**********************************************************
- */
-
- /**
- * Method that can be used to get hold of {@link JsonNodeFactory}
- * that this mapper will use when directly constructing
- * root {@link JsonNode} instances for Trees.
- *
- * Note: this is just a shortcut for calling
- *
- * getDeserializationConfig().getNodeFactory()
- *
- */
- public JsonNodeFactory getNodeFactory() {
- return _deserializationConfig.getNodeFactory();
- }
-
- /**
- * Method for specifying {@link JsonNodeFactory} to use for
- * constructing root level tree nodes (via method
- * {@link #createObjectNode}
- */
- public ObjectMapper setNodeFactory(JsonNodeFactory f) {
- _deserializationConfig = _deserializationConfig.with(f);
- return this;
- }
-
- /**
- * Method for adding specified {@link DeserializationProblemHandler}
- * to be used for handling specific problems during deserialization.
- */
- public ObjectMapper addHandler(DeserializationProblemHandler h) {
- _deserializationConfig = _deserializationConfig.withHandler(h);
- return this;
- }
-
- /**
- * Method for removing all registered {@link DeserializationProblemHandler}s
- * instances from this mapper.
- */
- public ObjectMapper clearProblemHandlers() {
- _deserializationConfig = _deserializationConfig.withNoProblemHandlers();
- return this;
- }
-
- /**
- * Method that allows overriding of the underlying {@link DeserializationConfig}
- * object.
- * It is added as a fallback method that may be used if no other configuration
- * modifier method works: it should not be used if there are alternatives,
- * and its use is generally discouraged.
- *
- * NOTE : only use this method if you know what you are doing -- it allows
- * by-passing some of checks applied to other configuration methods.
- * Also keep in mind that as with all configuration of {@link ObjectMapper},
- * this is only thread-safe if done before calling any deserialization methods.
- *
- * @since 2.4
- */
- public ObjectMapper setConfig(DeserializationConfig config) {
- _deserializationConfig = config;
- return this;
- }
-
- /*
- /**********************************************************
- /* Configuration, serialization
- /**********************************************************
- */
-
- /**
- * @deprecated Since 2.6, use {@link #setFilterProvider} instead (allows chaining)
- */
- @Deprecated
- public void setFilters(FilterProvider filterProvider) {
- _serializationConfig = _serializationConfig.withFilters(filterProvider);
- }
-
- /**
- * Method for configuring this mapper to use specified {@link FilterProvider} for
- * mapping Filter Ids to actual filter instances.
- *
- * Note that usually it is better to use method {@link #writer(FilterProvider)};
- * however, sometimes
- * this method is more convenient. For example, some frameworks only allow configuring
- * of ObjectMapper instances and not {@link ObjectWriter}s.
- *
- * @since 2.6
- */
- public ObjectMapper setFilterProvider(FilterProvider filterProvider) {
- _serializationConfig = _serializationConfig.withFilters(filterProvider);
- return this;
- }
-
+ /*
+ /**********************************************************************
+ /* Configuration: main config object access
+ /**********************************************************************
+ */
+
/**
- * Method that will configure default {@link Base64Variant} that
- * byte[]
serializers and deserializers will use.
- *
- * @param v Base64 variant to use
- *
- * @return This mapper, for convenience to allow chaining
- *
- * @since 2.1
+ * Accessor for internal configuration object that contains settings for
+ * serialization operations (writeValue(...)
methods)
+ *
+ * NOTE: Not to be used by application code; needed by some tests
*/
- public ObjectMapper setBase64Variant(Base64Variant v) {
- _serializationConfig = _serializationConfig.with(v);
- _deserializationConfig = _deserializationConfig.with(v);
- return this;
+ public SerializationConfig serializationConfig() {
+ return _serializationConfig;
}
/**
- * Method that allows overriding of the underlying {@link SerializationConfig}
- * object, which contains serialization-specific configuration settings.
- * It is added as a fallback method that may be used if no other configuration
- * modifier method works: it should not be used if there are alternatives,
- * and its use is generally discouraged.
- *
- * NOTE : only use this method if you know what you are doing -- it allows
- * by-passing some of checks applied to other configuration methods.
- * Also keep in mind that as with all configuration of {@link ObjectMapper},
- * this is only thread-safe if done before calling any serialization methods.
- *
- * @since 2.4
+ * Accessor for internal configuration object that contains settings for
+ * deserialization operations (readValue(...)
methods)
+ *
+ * NOTE: Not to be used by application code; needed by some tests
*/
- public ObjectMapper setConfig(SerializationConfig config) {
- _serializationConfig = config;
- return this;
+ public DeserializationConfig deserializationConfig() {
+ return _deserializationConfig;
}
-
- /*
- /**********************************************************
- /* Configuration, other
- /**********************************************************
- */
/**
- * Method that can be used to get hold of {@link JsonFactory} that this
+ * Method that can be used to get hold of {@link TokenStreamFactory} that this
* mapper uses if it needs to construct {@link JsonParser}s
* and/or {@link JsonGenerator}s.
*
* WARNING: note that all {@link ObjectReader} and {@link ObjectWriter}
* instances created by this mapper usually share the same configured
- * {@link JsonFactory}, so changes to its configuration will "leak".
+ * {@link TokenStreamFactory}, so changes to its configuration will "leak".
* To avoid such observed changes you should always use "with()" and
* "without()" method of {@link ObjectReader} and {@link ObjectWriter}
- * for changing {@link com.fasterxml.jackson.core.JsonParser.Feature}
- * and {@link com.fasterxml.jackson.core.JsonGenerator.Feature}
+ * for changing {@link StreamReadFeature}
+ * and {@link StreamWriteFeature}
* settings to use on per-call basis.
*
- * @return {@link JsonFactory} that this mapper uses when it needs to
+ * @return {@link TokenStreamFactory} that this mapper uses when it needs to
* construct Json parser and generators
*
- * @since 2.10
+ * @since 3.0
*/
- public JsonFactory tokenStreamFactory() { return _jsonFactory; }
+ public TokenStreamFactory tokenStreamFactory() { return _streamFactory; }
- @Override
- public JsonFactory getFactory() { return _jsonFactory; }
-
/**
- * @deprecated Since 2.1: Use {@link #getFactory} instead
+ * Method that can be used to get hold of {@link JsonNodeFactory}
+ * that this mapper will use when directly constructing
+ * root {@link JsonNode} instances for Trees.
+ *
+ * Note: this is just a shortcut for calling
+ *
+ * getDeserializationConfig().getNodeFactory()
+ *
*/
- @Deprecated
- @Override
- public JsonFactory getJsonFactory() { return getFactory(); }
-
- /**
- * Method for configuring the default {@link DateFormat} to use when serializing time
- * values as Strings, and deserializing from JSON Strings.
- * This is preferably to directly modifying {@link SerializationConfig} and
- * {@link DeserializationConfig} instances.
- * If you need per-request configuration, use {@link #writer(DateFormat)} to
- * create properly configured {@link ObjectWriter} and use that; this because
- * {@link ObjectWriter}s are thread-safe whereas ObjectMapper itself is only
- * thread-safe when configuring methods (such as this one) are NOT called.
- */
- public ObjectMapper setDateFormat(DateFormat dateFormat)
- {
- _deserializationConfig = _deserializationConfig.with(dateFormat);
- _serializationConfig = _serializationConfig.with(dateFormat);
- return this;
+ public JsonNodeFactory getNodeFactory() {
+ return _deserializationConfig.getNodeFactory();
}
- /**
- * @since 2.5
- */
- public DateFormat getDateFormat() {
- // arbitrary choice but let's do:
- return _serializationConfig.getDateFormat();
+ public InjectableValues getInjectableValues() {
+ return _injectableValues;
}
-
- /**
- * Method for configuring {@link HandlerInstantiator} to use for creating
- * instances of handlers (such as serializers, deserializers, type and type
- * id resolvers), given a class.
- *
- * @param hi Instantiator to use; if null, use the default implementation
+
+ /*
+ /**********************************************************************
+ /* Configuration, access to type factory, type resolution
+ /**********************************************************************
*/
- public Object setHandlerInstantiator(HandlerInstantiator hi)
- {
- _deserializationConfig = _deserializationConfig.with(hi);
- _serializationConfig = _serializationConfig.with(hi);
- return this;
- }
-
+
/**
- * Method for configuring {@link InjectableValues} which used to find
- * values to inject.
+ * Accessor for getting currently configured {@link TypeFactory} instance.
*/
- public ObjectMapper setInjectableValues(InjectableValues injectableValues) {
- _injectableValues = injectableValues;
- return this;
+ public TypeFactory getTypeFactory() {
+ return _typeFactory;
}
/**
- * @since 2.6
+ * Convenience method for constructing {@link JavaType} out of given
+ * type (typically java.lang.Class
), but without explicit
+ * context.
*/
- public InjectableValues getInjectableValues() {
- return _injectableValues;
+ public JavaType constructType(Type t) {
+ return _typeFactory.constructType(t);
}
- /**
- * Method for overriding default locale to use for formatting.
- * Default value used is {@link Locale#getDefault()}.
+ /*
+ /**********************************************************************
+ /* Configuration, accessing features
+ /**********************************************************************
*/
- public ObjectMapper setLocale(Locale l) {
- _deserializationConfig = _deserializationConfig.with(l);
- _serializationConfig = _serializationConfig.with(l);
- return this;
+
+ public boolean isEnabled(JsonFactory.Feature f) {
+ return _streamFactory.isEnabled(f);
}
- /**
- * Method for overriding default TimeZone to use for formatting.
- * Default value used is UTC (NOT default TimeZone of JVM).
- */
- public ObjectMapper setTimeZone(TimeZone tz) {
- _deserializationConfig = _deserializationConfig.with(tz);
- _serializationConfig = _serializationConfig.with(tz);
- return this;
+ public boolean isEnabled(StreamReadFeature f) {
+ return _deserializationConfig.isEnabled(f);
}
- /*
- /**********************************************************
- /* Configuration, simple features: MapperFeature
- /**********************************************************
- */
+ public boolean isEnabled(StreamWriteFeature f) {
+ return _serializationConfig.isEnabled(f);
+ }
/**
* Method for checking whether given {@link MapperFeature} is enabled.
@@ -1944,45 +508,15 @@ public boolean isEnabled(MapperFeature f) {
// ok to use either one, should be kept in sync
return _serializationConfig.isEnabled(f);
}
-
- /**
- * @deprecated Since 2.10 use {@code ObjectMapper.builder().disable(...)}
- */
- @Deprecated
- public ObjectMapper configure(MapperFeature f, boolean state) {
- _serializationConfig = state ?
- _serializationConfig.with(f) : _serializationConfig.without(f);
- _deserializationConfig = state ?
- _deserializationConfig.with(f) : _deserializationConfig.without(f);
- return this;
- }
-
- /**
- * @deprecated Since 2.10 use {@code ObjectMapper.builder().disable(...)}
- */
- @Deprecated
- public ObjectMapper enable(MapperFeature... f) {
- _deserializationConfig = _deserializationConfig.with(f);
- _serializationConfig = _serializationConfig.with(f);
- return this;
- }
/**
- * @deprecated Since 2.10 use {@code ObjectMapper.builder().disable(...)}
+ * Method for checking whether given deserialization-specific
+ * feature is enabled.
*/
- @Deprecated
- public ObjectMapper disable(MapperFeature... f) {
- _deserializationConfig = _deserializationConfig.without(f);
- _serializationConfig = _serializationConfig.without(f);
- return this;
+ public boolean isEnabled(DeserializationFeature f) {
+ return _deserializationConfig.isEnabled(f);
}
- /*
- /**********************************************************
- /* Configuration, simple features: SerializationFeature
- /**********************************************************
- */
-
/**
* Method for checking whether given serialization-specific
* feature is enabled.
@@ -1991,286 +525,244 @@ public boolean isEnabled(SerializationFeature f) {
return _serializationConfig.isEnabled(f);
}
- /**
- * Method for changing state of an on/off serialization feature for
- * this object mapper.
- */
- public ObjectMapper configure(SerializationFeature f, boolean state) {
- _serializationConfig = state ?
- _serializationConfig.with(f) : _serializationConfig.without(f);
- return this;
- }
-
- /**
- * Method for enabling specified {@link DeserializationConfig} feature.
- * Modifies and returns this instance; no new object is created.
+ /*
+ /**********************************************************************
+ /* Configuration, accessing module information
+ /**********************************************************************
*/
- public ObjectMapper enable(SerializationFeature f) {
- _serializationConfig = _serializationConfig.with(f);
- return this;
- }
/**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ * Method that may be used to find out {@link Module}s that were registered
+ * when creating this mapper (if any).
+ *
+ * @since 3.0
*/
- public ObjectMapper enable(SerializationFeature first,
- SerializationFeature... f) {
- _serializationConfig = _serializationConfig.with(first, f);
- return this;
+ public Collection getRegisteredModules() {
+ return _savedBuilderState.modules();
}
- /**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ /*
+ /**********************************************************************
+ /* Public API: constructing Parsers that are properly linked
+ /* to `ObjectReadContext`
+ /**********************************************************************
*/
- public ObjectMapper disable(SerializationFeature f) {
- _serializationConfig = _serializationConfig.without(f);
- return this;
- }
/**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,java.io.File)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper disable(SerializationFeature first,
- SerializationFeature... f) {
- _serializationConfig = _serializationConfig.without(first, f);
- return this;
+ public JsonParser createParser(File src) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, src));
}
-
- /*
- /**********************************************************
- /* Configuration, simple features: DeserializationFeature
- /**********************************************************
- */
/**
- * Method for checking whether given deserialization-specific
- * feature is enabled.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,java.net.URL)}.
+ *
+ * @since 3.0
*/
- public boolean isEnabled(DeserializationFeature f) {
- return _deserializationConfig.isEnabled(f);
+ public JsonParser createParser(URL src) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, src));
}
/**
- * Method for changing state of an on/off deserialization feature for
- * this object mapper.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,InputStream)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper configure(DeserializationFeature f, boolean state) {
- _deserializationConfig = state ?
- _deserializationConfig.with(f) : _deserializationConfig.without(f);
- return this;
+ public JsonParser createParser(InputStream in) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, in));
}
/**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,Reader)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper enable(DeserializationFeature feature) {
- _deserializationConfig = _deserializationConfig.with(feature);
- return this;
+ public JsonParser createParser(Reader r) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, r));
}
/**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,byte[])}.
+ *
+ * @since 3.0
*/
- public ObjectMapper enable(DeserializationFeature first,
- DeserializationFeature... f) {
- _deserializationConfig = _deserializationConfig.with(first, f);
- return this;
+ public JsonParser createParser(byte[] data) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, data));
}
-
+
/**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,byte[],int,int)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper disable(DeserializationFeature feature) {
- _deserializationConfig = _deserializationConfig.without(feature);
- return this;
+ public JsonParser createParser(byte[] data, int offset, int len) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, data, offset, len));
}
/**
- * Method for enabling specified {@link DeserializationConfig} features.
- * Modifies and returns this instance; no new object is created.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,String)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper disable(DeserializationFeature first,
- DeserializationFeature... f) {
- _deserializationConfig = _deserializationConfig.without(first, f);
- return this;
+ public JsonParser createParser(String content) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, content));
}
-
- /*
- /**********************************************************
- /* Configuration, simple features: JsonParser.Feature
- /**********************************************************
- */
- public boolean isEnabled(JsonParser.Feature f) {
- return _deserializationConfig.isEnabled(f, _jsonFactory);
+ /**
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,char[])}.
+ *
+ * @since 3.0
+ */
+ public JsonParser createParser(char[] content) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, content));
}
/**
- * Method for changing state of specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s
- * for parser instances this object mapper creates.
- *
- * Note that this is equivalent to directly calling same method
- * on {@link #getFactory}.
- *
- * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
- * it will change observed configuration by {@link ObjectReader}s as well -- to avoid
- * this, use {@link ObjectReader#with(JsonParser.Feature)} instead.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,char[],int,int)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper configure(JsonParser.Feature f, boolean state) {
- _jsonFactory.configure(f, state);
- return this;
+ public JsonParser createParser(char[] content, int offset, int len) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, content, offset, len));
}
/**
- * Method for enabling specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s
- * for parser instances this object mapper creates.
- *
- * Note that this is equivalent to directly calling same method on {@link #getFactory}.
- *
- * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
- * it will change observed configuration by {@link ObjectReader}s as well -- to avoid
- * this, use {@link ObjectReader#with(JsonParser.Feature)} instead.
+ * Factory method for constructing {@link JsonParser} that is properly
+ * wired to allow callbacks for deserialization: basically
+ * constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,DataInput)}.
*
- * @since 2.5
+ * @since 3.0
*/
- public ObjectMapper enable(JsonParser.Feature... features) {
- for (JsonParser.Feature f : features) {
- _jsonFactory.enable(f);
- }
- return this;
+ public JsonParser createParser(DataInput content) throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, content));
}
-
+
/**
- * Method for disabling specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s
- * for parser instances this object mapper creates.
- *
- * Note that this is equivalent to directly calling same method on {@link #getFactory}.
- *
- * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
- * it will change observed configuration by {@link ObjectReader}s as well -- to avoid
- * this, use {@link ObjectReader#without(JsonParser.Feature)} instead.
+ * Factory method for constructing non-blocking {@link JsonParser} that is properly
+ * wired to allow configuration access (and, if relevant for parser, callbacks):
+ * essentially constructs a {@link ObjectReadContext} and then calls
+ * {@link TokenStreamFactory#createParser(ObjectReadContext,DataInput)}.
*
- * @since 2.5
+ * @since 3.0
*/
- public ObjectMapper disable(JsonParser.Feature... features) {
- for (JsonParser.Feature f : features) {
- _jsonFactory.disable(f);
- }
- return this;
+ public JsonParser createNonBlockingByteArrayParser() throws IOException {
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return ctxt.assignAndReturnParser(_streamFactory.createNonBlockingByteArrayParser(ctxt));
}
-
+
/*
- /**********************************************************
- /* Configuration, simple features: JsonGenerator.Feature
- /**********************************************************
+ /**********************************************************************
+ /* Public API: constructing Generator that are properly linked
+ /* to `ObjectWriteContext`
+ /**********************************************************************
*/
- public boolean isEnabled(JsonGenerator.Feature f) {
- return _serializationConfig.isEnabled(f, _jsonFactory);
- }
-
/**
- * Method for changing state of an on/off {@link JsonGenerator} feature for
- * generator instances this object mapper creates.
- *
- * Note that this is equivalent to directly calling same method
- * on {@link #getFactory}.
- *
- * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
- * it will change observed configuration by {@link ObjectWriter}s as well -- to avoid
- * this, use {@link ObjectWriter#with(JsonGenerator.Feature)} instead.
+ * Factory method for constructing {@link JsonGenerator} that is properly
+ * wired to allow callbacks for serialization: basically
+ * constructs a {@link ObjectWriteContext} and then calls
+ * {@link TokenStreamFactory#createGenerator(ObjectWriteContext,OutputStream)}.
+ *
+ * @since 3.0
*/
- public ObjectMapper configure(JsonGenerator.Feature f, boolean state) {
- _jsonFactory.configure(f, state);
- return this;
+ public JsonGenerator createGenerator(OutputStream out) throws IOException {
+ return _streamFactory.createGenerator(_serializerProvider(), out);
}
/**
- * Method for enabling specified {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s
- * for parser instances this object mapper creates.
- *
- * Note that this is equivalent to directly calling same method on {@link #getFactory}.
- *
- * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
- * it will change observed configuration by {@link ObjectWriter}s as well -- to avoid
- * this, use {@link ObjectWriter#with(JsonGenerator.Feature)} instead.
+ * Factory method for constructing {@link JsonGenerator} that is properly
+ * wired to allow callbacks for serialization: basically
+ * constructs a {@link ObjectWriteContext} and then calls
+ * {@link TokenStreamFactory#createGenerator(ObjectWriteContext,OutputStream,JsonEncoding)}.
*
- * @since 2.5
+ * @since 3.0
*/
- public ObjectMapper enable(JsonGenerator.Feature... features) {
- for (JsonGenerator.Feature f : features) {
- _jsonFactory.enable(f);
- }
- return this;
+ public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException {
+ return _streamFactory.createGenerator(_serializerProvider(), out, enc);
}
/**
- * Method for disabling specified {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s
- * for parser instances this object mapper creates.
- *
- * Note that this is equivalent to directly calling same method on {@link #getFactory}.
- *
- * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
- * it will change observed configuration by {@link ObjectWriter}s as well -- to avoid
- * this, use {@link ObjectWriter#without(JsonGenerator.Feature)} instead.
+ * Factory method for constructing {@link JsonGenerator} that is properly
+ * wired to allow callbacks for serialization: basically
+ * constructs a {@link ObjectWriteContext} and then calls
+ * {@link TokenStreamFactory#createGenerator(ObjectWriteContext,Writer)}.
*
- * @since 2.5
+ * @since 3.0
*/
- public ObjectMapper disable(JsonGenerator.Feature... features) {
- for (JsonGenerator.Feature f : features) {
- _jsonFactory.disable(f);
- }
- return this;
+ public JsonGenerator createGenerator(Writer w) throws IOException {
+ return _streamFactory.createGenerator(_serializerProvider(), w);
}
- /*
- /**********************************************************
- /* Configuration, simple features: JsonFactory.Feature
- /**********************************************************
- */
-
/**
- * Convenience method, equivalent to:
- *
- * getJsonFactory().isEnabled(f);
- *
+ * Factory method for constructing {@link JsonGenerator} that is properly
+ * wired to allow callbacks for serialization: basically
+ * constructs a {@link ObjectWriteContext} and then calls
+ * {@link TokenStreamFactory#createGenerator(ObjectWriteContext,File,JsonEncoding)}.
+ *
+ * @since 3.0
*/
- public boolean isEnabled(JsonFactory.Feature f) {
- return _jsonFactory.isEnabled(f);
+ public JsonGenerator createGenerator(File f, JsonEncoding enc)
+ throws IOException {
+ return _streamFactory.createGenerator(_serializerProvider(), f, enc);
}
- /*
- /**********************************************************
- /* Configuration, 2.10+ stream features
- /**********************************************************
- */
-
/**
- * @since 2.10
+ * Factory method for constructing {@link JsonGenerator} that is properly
+ * wired to allow callbacks for serialization: basically
+ * constructs a {@link ObjectWriteContext} and then calls
+ * {@link TokenStreamFactory#createGenerator(ObjectWriteContext,DataOutput)}.
+ *
+ * @since 3.0
*/
- public boolean isEnabled(StreamReadFeature f) {
- return isEnabled(f.mappedFeature());
+ public JsonGenerator createGenerator(DataOutput out) throws IOException {
+ return _streamFactory.createGenerator(_serializerProvider(), out);
}
- /**
- * @since 2.10
- */
- public boolean isEnabled(StreamWriteFeature f) {
- return isEnabled(f.mappedFeature());
- }
-
/*
- /**********************************************************
- /* Public API (from ObjectCodec): deserialization
- /* (mapping from JSON to Java types);
- /* main methods
- /**********************************************************
+ /**********************************************************************
+ /* Public API deserialization, main methods
+ /**********************************************************************
*/
/**
@@ -2292,12 +784,12 @@ public boolean isEnabled(StreamWriteFeature f) {
* @throws JsonMappingException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*/
- @Override
@SuppressWarnings("unchecked")
public T readValue(JsonParser p, Class valueType)
throws IOException, JsonParseException, JsonMappingException
{
- return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueType));
+ DeserializationContext ctxt = createDeserializationContext(p);
+ return (T) _readValue(ctxt, p, _typeFactory.constructType(valueType));
}
/**
@@ -2316,12 +808,12 @@ public T readValue(JsonParser p, Class valueType)
* @throws JsonMappingException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*/
- @Override
@SuppressWarnings("unchecked")
public T readValue(JsonParser p, TypeReference valueTypeRef)
throws IOException, JsonParseException, JsonMappingException
{
- return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueTypeRef));
+ DeserializationContext ctxt = createDeserializationContext(p);
+ return (T) _readValue(ctxt, p, _typeFactory.constructType(valueTypeRef));
}
/**
@@ -2339,12 +831,12 @@ public T readValue(JsonParser p, TypeReference valueTypeRef)
* @throws JsonMappingException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*/
- @Override
@SuppressWarnings("unchecked")
public final T readValue(JsonParser p, ResolvedType valueType)
throws IOException, JsonParseException, JsonMappingException
{
- return (T) _readValue(getDeserializationConfig(), p, (JavaType) valueType);
+ DeserializationContext ctxt = createDeserializationContext(p);
+ return (T) _readValue(ctxt, p, (JavaType) valueType);
}
/**
@@ -2363,9 +855,10 @@ public final T readValue(JsonParser p, ResolvedType valueType)
public T readValue(JsonParser p, JavaType valueType)
throws IOException, JsonParseException, JsonMappingException
{
- return (T) _readValue(getDeserializationConfig(), p, valueType);
+ DeserializationContext ctxt = createDeserializationContext(p);
+ return (T) _readValue(ctxt, p, valueType);
}
-
+
/**
* Method to deserialize JSON content as a tree {@link JsonNode}.
* Returns {@link JsonNode} that represents the root of the resulting tree, if there
@@ -2389,21 +882,20 @@ public T readValue(JsonParser p, JavaType valueType)
* @throws JsonParseException if underlying input contains invalid content
* of type {@link JsonParser} supports (JSON for default case)
*/
- @Override
public T readTree(JsonParser p)
throws IOException, JsonProcessingException
{
// Must check for EOF here before calling readValue(), since that'll choke on it otherwise
- DeserializationConfig cfg = getDeserializationConfig();
- JsonToken t = p.getCurrentToken();
+ JsonToken t = p.currentToken();
if (t == null) {
t = p.nextToken();
if (t == null) {
return null;
}
}
+ DeserializationContext ctxt = createDeserializationContext(p);
// NOTE! _readValue() will check for trailing tokens
- JsonNode n = (JsonNode) _readValue(cfg, p, JSON_NODE_TYPE);
+ JsonNode n = (JsonNode) _readValue(ctxt, p, JSON_NODE_TYPE);
if (n == null) {
n = getNodeFactory().nullNode();
}
@@ -2430,26 +922,10 @@ public T readTree(JsonParser p)
*
* Note that {@link ObjectReader} has more complete set of variants.
*/
- @Override
- public MappingIterator readValues(JsonParser p, ResolvedType valueType)
- throws IOException, JsonProcessingException
- {
- return readValues(p, (JavaType) valueType);
- }
-
- /**
- * Convenience method, equivalent in function to:
- *
- * readerFor(valueType).readValues(p);
- *
- *
- * Type-safe overload of {@link #readValues(JsonParser, ResolvedType)}.
- */
public MappingIterator readValues(JsonParser p, JavaType valueType)
throws IOException, JsonProcessingException
{
- DeserializationConfig config = getDeserializationConfig();
- DeserializationContext ctxt = createDeserializationContext(p, config);
+ DeserializationContext ctxt = createDeserializationContext(p);
JsonDeserializer> deser = _findRootDeserializer(ctxt, valueType);
// false -> do NOT close JsonParser (since caller passed it)
return new MappingIterator(valueType, p, ctxt, deser,
@@ -2462,30 +938,19 @@ public MappingIterator readValues(JsonParser p, JavaType valueType)
* readerFor(valueType).readValues(p);
*
*
- * Type-safe overload of {@link #readValues(JsonParser, ResolvedType)}.
+ * Type-safe overload of {@link #readValues(JsonParser, JavaType)}.
*/
- @Override
public MappingIterator readValues(JsonParser p, Class valueType)
throws IOException, JsonProcessingException
{
return readValues(p, _typeFactory.constructType(valueType));
}
- /**
- * Method for reading sequence of Objects from parser stream.
- */
- @Override
- public MappingIterator readValues(JsonParser p, TypeReference valueTypeRef)
- throws IOException, JsonProcessingException
- {
- return readValues(p, _typeFactory.constructType(valueTypeRef));
- }
-
/*
- /**********************************************************
- /* Public API not included in ObjectCodec: deserialization
- /* (mapping from JSON to Java types)
- /**********************************************************
+ /**********************************************************************
+ /* Public API: deserialization
+ /* (mapping from token stream to Java types)
+ /**********************************************************************
*/
/**
@@ -2516,7 +981,8 @@ public MappingIterator readValues(JsonParser p, TypeReference valueTyp
*/
public JsonNode readTree(InputStream in) throws IOException
{
- return _readTreeAndClose(_jsonFactory.createParser(in));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, in));
}
/**
@@ -2524,7 +990,8 @@ public JsonNode readTree(InputStream in) throws IOException
* passed-in {@link Reader}
*/
public JsonNode readTree(Reader r) throws IOException {
- return _readTreeAndClose(_jsonFactory.createParser(r));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, r));
}
/**
@@ -2532,7 +999,8 @@ public JsonNode readTree(Reader r) throws IOException {
* passed-in {@link String}
*/
public JsonNode readTree(String content) throws IOException {
- return _readTreeAndClose(_jsonFactory.createParser(content));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, content));
}
/**
@@ -2540,7 +1008,8 @@ public JsonNode readTree(String content) throws IOException {
* passed-in byte array.
*/
public JsonNode readTree(byte[] content) throws IOException {
- return _readTreeAndClose(_jsonFactory.createParser(content));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, content));
}
/**
@@ -2548,7 +1017,8 @@ public JsonNode readTree(byte[] content) throws IOException {
* passed-in byte array.
*/
public JsonNode readTree(byte[] content, int offset, int len) throws IOException {
- return _readTreeAndClose(_jsonFactory.createParser(content, offset, len));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, content, offset, len));
}
/**
@@ -2558,7 +1028,8 @@ public JsonNode readTree(byte[] content, int offset, int len) throws IOException
public JsonNode readTree(File file)
throws IOException, JsonProcessingException
{
- return _readTreeAndClose(_jsonFactory.createParser(file));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, file));
}
/**
@@ -2566,37 +1037,34 @@ public JsonNode readTree(File file)
* passed-in {@link URL}.
*/
public JsonNode readTree(URL source) throws IOException {
- return _readTreeAndClose(_jsonFactory.createParser(source));
+ DeserializationContext ctxt = createDeserializationContext();
+ return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, source));
}
/*
- /**********************************************************
- /* Public API (from ObjectCodec): serialization
- /* (mapping from Java types to Json)
- /**********************************************************
+ /**********************************************************************
+ /* Public API serialization
+ /* (mapping from Java types to token streams)
+ /**********************************************************************
*/
/**
* Method that can be used to serialize any Java value as
* JSON output, using provided {@link JsonGenerator}.
*/
- @Override
public void writeValue(JsonGenerator g, Object value)
throws IOException, JsonGenerationException, JsonMappingException
{
- SerializationConfig config = getSerializationConfig();
-
- /* 12-May-2015/2.6, tatu: Looks like we do NOT want to call the usual
- * 'config.initialize(g)` here, since it is assumed that generator
- * has been configured by caller. But for some reason we don't
- * trust indentation settings...
- */
- // 10-Aug-2012, tatu: as per [Issue#12], must handle indentation:
+ SerializationConfig config = serializationConfig();
+ // 04-Oct-2017, tatu: Generator should come properly configured and we should not
+ // change its state in any way, I think (at least with Jackson 3.0)
+ /*
if (config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
if (g.getPrettyPrinter() == null) {
g.setPrettyPrinter(config.constructDefaultPrettyPrinter());
}
}
+ */
if (config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
_writeCloseableValue(g, value, config);
} else {
@@ -2608,19 +1076,18 @@ public void writeValue(JsonGenerator g, Object value)
}
/*
- /**********************************************************
- /* Public API (from TreeCodec via ObjectCodec): Tree Model support
- /**********************************************************
+ /**********************************************************************
+ /* Public API: Tree Model support
+ /**********************************************************************
*/
- @Override
- public void writeTree(JsonGenerator jgen, TreeNode rootNode)
+ public void writeTree(JsonGenerator g, TreeNode rootNode)
throws IOException, JsonProcessingException
{
- SerializationConfig config = getSerializationConfig();
- _serializerProvider(config).serializeValue(jgen, rootNode);
+ SerializationConfig config = serializationConfig();
+ _serializerProvider(config).serializeValue(g, rootNode);
if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
- jgen.flush();
+ g.flush();
}
}
@@ -2628,13 +1095,13 @@ public void writeTree(JsonGenerator jgen, TreeNode rootNode)
* Method to serialize given JSON Tree, using generator
* provided.
*/
- public void writeTree(JsonGenerator jgen, JsonNode rootNode)
+ public void writeTree(JsonGenerator g, JsonNode rootNode)
throws IOException, JsonProcessingException
{
- SerializationConfig config = getSerializationConfig();
- _serializerProvider(config).serializeValue(jgen, rootNode);
+ SerializationConfig config = serializationConfig();
+ _serializerProvider(config).serializeValue(g, rootNode);
if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
- jgen.flush();
+ g.flush();
}
}
@@ -2645,7 +1112,6 @@ public void writeTree(JsonGenerator jgen, JsonNode rootNode)
* part of core package, whereas impls are part of mapper
* package)
*/
- @Override
public ObjectNode createObjectNode() {
return _deserializationConfig.getNodeFactory().objectNode();
}
@@ -2657,7 +1123,6 @@ public ObjectNode createObjectNode() {
* part of core package, whereas impls are part of mapper
* package)
*/
- @Override
public ArrayNode createArrayNode() {
return _deserializationConfig.getNodeFactory().arrayNode();
}
@@ -2668,9 +1133,9 @@ public ArrayNode createArrayNode() {
*
* @param n Root node of the tree that resulting parser will read from
*/
- @Override
public JsonParser treeAsTokens(TreeNode n) {
- return new TreeTraversingParser((JsonNode) n, this);
+ DeserializationContext ctxt = createDeserializationContext();
+ return new TreeTraversingParser((JsonNode) n, ctxt);
}
/**
@@ -2683,7 +1148,6 @@ public JsonParser treeAsTokens(TreeNode n) {
*
*/
@SuppressWarnings("unchecked")
- @Override
public T treeToValue(TreeNode n, Class valueType)
throws JsonProcessingException
{
@@ -2736,14 +1200,23 @@ public T treeToValue(TreeNode n, Class valueType)
public T valueToTree(Object fromValue)
throws IllegalArgumentException
{
- if (fromValue == null) return null;
- TokenBuffer buf = new TokenBuffer(this, false);
+ if (fromValue == null) {
+ return null;
+ }
+ // 06-Oct-2017, tatu: `convertValue()` disables root value wrapping so
+ // do it here too
+ SerializationConfig config = serializationConfig()
+ .without(SerializationFeature.WRAP_ROOT_VALUE);
+ DefaultSerializerProvider prov = _serializerProvider(config);
+ TokenBuffer buf = TokenBuffer.forValueConversion(prov);
+ // Would like to let buffer decide, but it won't have deser config to check so...
if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
buf = buf.forceUseOfBigDecimal(true);
}
JsonNode result;
try {
- writeValue(buf, fromValue);
+ // Equivalent to `writeValue()`, basically:
+ prov.serializeValue(buf, fromValue);
JsonParser p = buf.asParser();
result = readTree(p);
p.close();
@@ -2751,85 +1224,12 @@ public T valueToTree(Object fromValue)
throw new IllegalArgumentException(e.getMessage(), e);
}
return (T) result;
- }
-
- /*
- /**********************************************************
- /* Extended Public API, accessors
- /**********************************************************
- */
-
- /**
- * Method that can be called to check whether mapper thinks
- * it could serialize an instance of given Class.
- * Check is done
- * by checking whether a serializer can be found for the type.
- *
- * NOTE: since this method does NOT throw exceptions, but internal
- * processing may, caller usually has little information as to why
- * serialization would fail. If you want access to internal {@link Exception},
- * call {@link #canSerialize(Class, AtomicReference)} instead.
- *
- * @return True if mapper can find a serializer for instances of
- * given class (potentially serializable), false otherwise (not
- * serializable)
- */
- public boolean canSerialize(Class> type) {
- return _serializerProvider(getSerializationConfig()).hasSerializerFor(type, null);
- }
-
- /**
- * Method similar to {@link #canSerialize(Class)} but that can return
- * actual {@link Throwable} that was thrown when trying to construct
- * serializer: this may be useful in figuring out what the actual problem is.
- *
- * @since 2.3
- */
- public boolean canSerialize(Class> type, AtomicReference cause) {
- return _serializerProvider(getSerializationConfig()).hasSerializerFor(type, cause);
- }
-
- /**
- * Method that can be called to check whether mapper thinks
- * it could deserialize an Object of given type.
- * Check is done by checking whether a registered deserializer can
- * be found or built for the type; if not (either by no mapping being
- * found, or through an Exception
being thrown, false
- * is returned.
- *
- * NOTE : in case an exception is thrown during course of trying
- * co construct matching deserializer, it will be effectively swallowed.
- * If you want access to that exception, call
- * {@link #canDeserialize(JavaType, AtomicReference)} instead.
- *
- * @return True if mapper can find a serializer for instances of
- * given class (potentially serializable), false otherwise (not
- * serializable)
- */
- public boolean canDeserialize(JavaType type)
- {
- return createDeserializationContext(null,
- getDeserializationConfig()).hasValueDeserializerFor(type, null);
}
- /**
- * Method similar to {@link #canDeserialize(JavaType)} but that can return
- * actual {@link Throwable} that was thrown when trying to construct
- * serializer: this may be useful in figuring out what the actual problem is.
- *
- * @since 2.3
- */
- public boolean canDeserialize(JavaType type, AtomicReference cause)
- {
- return createDeserializationContext(null,
- getDeserializationConfig()).hasValueDeserializerFor(type, cause);
- }
-
/*
- /**********************************************************
- /* Extended Public API, deserialization,
- /* convenience methods
- /**********************************************************
+ /**********************************************************************
+ /* Public API, deserialization (ext format to Java Objects)
+ /**********************************************************************
*/
/**
@@ -2845,10 +1245,11 @@ public boolean canDeserialize(JavaType type, AtomicReference cause)
* expected for result type (or has other mismatch issues)
*/
@SuppressWarnings("unchecked")
- public T readValue(File src, Class valueType)
- throws IOException, JsonParseException, JsonMappingException
+ public T readValue(File src, Class valueType) throws IOException
{
- return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return (T) _readMapAndClose(ctxt, _streamFactory.createParser(ctxt, src),
+ _typeFactory.constructType(valueType));
}
/**
@@ -2864,10 +1265,11 @@ public T readValue(File src, Class valueType)
* expected for result type (or has other mismatch issues)
*/
@SuppressWarnings({ "unchecked" })
- public T readValue(File src, TypeReference valueTypeRef)
- throws IOException, JsonParseException, JsonMappingException
+ public T readValue(File src, TypeReference valueTypeRef) throws IOException
{
- return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
+ DefaultDeserializationContext ctxt = createDeserializationContext();
+ return (T) _readMapAndClose(ctxt, _streamFactory.createParser(ctxt, src),
+ _typeFactory.constructType(valueTypeRef));
}
/**
@@ -2886,7 +1288,8 @@ public T readValue(File src, TypeReference valueTypeRef)
public