T _throwSubtypeClassNotAllowed(JavaType baseType, String subType,
PolymorphicTypeValidator ptv) throws JsonMappingException {
throw invalidTypeIdException(baseType, subType,
"Configured `PolymorphicTypeValidator` (of type "+ClassUtil.classNameOf(ptv)+") denied resolution");
}
/**
* Helper method for constructing exception to indicate that given type id
* could not be resolved to a valid subtype of specified base type.
* Most commonly called during polymorphic deserialization.
*
* Note that most of the time this method should NOT be called directly: instead,
* method handleUnknownTypeId()
should be called which will call this method
* if necessary.
*
* @since 2.9
*/
protected abstract JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
String extraDesc);
public abstract TypeFactory getTypeFactory();
/*
/**********************************************************
/* Helper object construction
/**********************************************************
*/
public ObjectIdGenerator> objectIdGeneratorInstance(Annotated annotated,
ObjectIdInfo objectIdInfo)
throws JsonMappingException
{
Class> implClass = objectIdInfo.getGeneratorType();
final MapperConfig> config = getConfig();
HandlerInstantiator hi = config.getHandlerInstantiator();
ObjectIdGenerator> gen = (hi == null) ? null : hi.objectIdGeneratorInstance(config, annotated, implClass);
if (gen == null) {
gen = (ObjectIdGenerator>) ClassUtil.createInstance(implClass,
config.canOverrideAccessModifiers());
}
return gen.forScope(objectIdInfo.getScope());
}
public ObjectIdResolver objectIdResolverInstance(Annotated annotated, ObjectIdInfo objectIdInfo)
{
Class extends ObjectIdResolver> implClass = objectIdInfo.getResolverType();
final MapperConfig> config = getConfig();
HandlerInstantiator hi = config.getHandlerInstantiator();
ObjectIdResolver resolver = (hi == null) ? null : hi.resolverIdGeneratorInstance(config, annotated, implClass);
if (resolver == null) {
resolver = ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers());
}
return resolver;
}
/**
* Helper method to use to construct a {@link Converter}, given a definition
* that may be either actual converter instance, or Class for instantiating one.
*
* @since 2.2
*/
@SuppressWarnings("unchecked")
public Converter converterInstance(Annotated annotated,
Object converterDef)
throws JsonMappingException
{
if (converterDef == null) {
return null;
}
if (converterDef instanceof Converter,?>) {
return (Converter) converterDef;
}
if (!(converterDef instanceof Class)) {
throw new IllegalStateException("AnnotationIntrospector returned Converter definition of type "
+converterDef.getClass().getName()+"; expected type Converter or Class instead");
}
Class> converterClass = (Class>)converterDef;
// there are some known "no class" markers to consider too:
if (converterClass == Converter.None.class || ClassUtil.isBogusClass(converterClass)) {
return null;
}
if (!Converter.class.isAssignableFrom(converterClass)) {
throw new IllegalStateException("AnnotationIntrospector returned Class "
+converterClass.getName()+"; expected Class");
}
final MapperConfig> config = getConfig();
HandlerInstantiator hi = config.getHandlerInstantiator();
Converter,?> conv = (hi == null) ? null : hi.converterInstance(config, annotated, converterClass);
if (conv == null) {
conv = (Converter,?>) ClassUtil.createInstance(converterClass,
config.canOverrideAccessModifiers());
}
return (Converter) conv;
}
/*
/**********************************************************
/* Error reporting
/**********************************************************
*/
/**
* Helper method called to indicate a generic problem that stems from type
* definition(s), not input data, or input/output state; typically this
* means throwing a {@link com.fasterxml.jackson.databind.exc.InvalidDefinitionException}.
*
* @since 2.9
*/
public abstract T reportBadDefinition(JavaType type, String msg) throws JsonMappingException;
/**
* @since 2.9
*/
public T reportBadDefinition(Class> type, String msg) throws JsonMappingException {
return reportBadDefinition(constructType(type), msg);
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
/**
* @since 2.9
*/
protected final String _format(String msg, Object... msgArgs) {
if (msgArgs.length > 0) {
return String.format(msg, msgArgs);
}
return msg;
}
/**
* @since 2.9
*/
protected final String _truncate(String desc) {
if (desc == null) {
return "";
}
if (desc.length() <= MAX_ERROR_STR_LEN) {
return 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]";
}
// !!! 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;
}
return msgBase + ": " + extra;
}
/**
* @since 2.9
*/
protected String _desc(String desc) {
if (desc == null) {
return "[N/A]";
}
// !!! should we quote it? (in case there are control chars, linefeeds)
return _truncate(desc);
}
}
DeserializationConfig.java 0000664 0000000 0000000 00000076624 13604243101 0035650 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind 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.util.LinkedNode;
import com.fasterxml.jackson.databind.util.RootNameLookup;
/**
* Object that contains baseline configuration for deserialization
* process. An instance is owned by {@link ObjectMapper}, which
* passes an immutable instance to be used for deserialization process.
*
* Note that instances are considered immutable and as such no copies
* should need to be created for sharing; all copying is done with
* "fluent factory" methods.
*/
public final class DeserializationConfig
extends MapperConfigBase
implements java.io.Serializable // since 2.1
{
// since 2.9
private static final long serialVersionUID = 2;
// since 2.10.1
private final static int DESER_FEATURE_DEFAULTS = collectFeatureDefaults(DeserializationFeature.class);
/*
/**********************************************************
/* 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;
/*
/**********************************************************
/* Deserialization features
/**********************************************************
*/
/**
* Set of {@link DeserializationFeature}s enabled.
*/
protected final int _deserFeatures;
/*
/**********************************************************
/* Parser features: generic, format-specific
/**********************************************************
*/
/**
* States of {@link com.fasterxml.jackson.core.JsonParser.Feature}s to enable/disable.
*/
protected final int _parserFeatures;
/**
* Bitflag of {@link com.fasterxml.jackson.core.JsonParser.Feature}s to enable/disable
*/
protected final int _parserFeaturesToChange;
/**
* States of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable.
*
* @since 2.7
*/
protected final int _formatReadFeatures;
/**
* Bitflag of {@link com.fasterxml.jackson.core.FormatFeature}s to enable/disable
*
* @since 2.7
*/
protected final int _formatReadFeaturesToChange;
/*
/**********************************************************
/* Life-cycle, primary constructors for new instances
/**********************************************************
*/
/**
* Constructor used by ObjectMapper to create default configuration object instance.
*/
public DeserializationConfig(BaseSettings base,
SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames,
ConfigOverrides configOverrides)
{
super(base, str, mixins, rootNames, configOverrides);
_deserFeatures = DESER_FEATURE_DEFAULTS;
_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;
}
/*
/**********************************************************
/* 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)
{
super(src, mapperFeatures);
_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;
_problemHandlers = src._problemHandlers;
_parserFeatures = src._parserFeatures;
_parserFeaturesToChange = src._parserFeaturesToChange;
_formatReadFeatures = src._formatReadFeatures;
_formatReadFeaturesToChange = src._formatReadFeaturesToChange;
}
private DeserializationConfig(DeserializationConfig src, BaseSettings base)
{
super(src, base);
_deserFeatures = src._deserFeatures;
_nodeFactory = src._nodeFactory;
_problemHandlers = src._problemHandlers;
_parserFeatures = src._parserFeatures;
_parserFeaturesToChange = src._parserFeaturesToChange;
_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;
}
private DeserializationConfig(DeserializationConfig src,
LinkedNode problemHandlers)
{
super(src);
_deserFeatures = src._deserFeatures;
_problemHandlers = problemHandlers;
_nodeFactory = src._nodeFactory;
_parserFeatures = src._parserFeatures;
_parserFeaturesToChange = src._parserFeaturesToChange;
_formatReadFeatures = src._formatReadFeatures;
_formatReadFeaturesToChange = src._formatReadFeaturesToChange;
}
private DeserializationConfig(DeserializationConfig src, PropertyName rootName)
{
super(src, rootName);
_deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
_nodeFactory = src._nodeFactory;
_parserFeatures = src._parserFeatures;
_parserFeaturesToChange = src._parserFeaturesToChange;
_formatReadFeatures = src._formatReadFeatures;
_formatReadFeaturesToChange = src._formatReadFeaturesToChange;
}
private DeserializationConfig(DeserializationConfig src, Class> view)
{
super(src, view);
_deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
_nodeFactory = src._nodeFactory;
_parserFeatures = src._parserFeatures;
_parserFeaturesToChange = src._parserFeaturesToChange;
_formatReadFeatures = src._formatReadFeatures;
_formatReadFeaturesToChange = src._formatReadFeaturesToChange;
}
protected DeserializationConfig(DeserializationConfig src, ContextAttributes attrs)
{
super(src, attrs);
_deserFeatures = src._deserFeatures;
_problemHandlers = src._problemHandlers;
_nodeFactory = src._nodeFactory;
_parserFeatures = src._parserFeatures;
_parserFeaturesToChange = src._parserFeaturesToChange;
_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;
}
// for unit tests only:
protected BaseSettings getBaseSettings() { return _base; }
/*
/**********************************************************
/* Life-cycle, general factory methods from MapperConfig(Base)
/**********************************************************
*/
@Override // since 2.9
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) {
if (_rootName == null) {
return this;
}
} else if (rootName.equals(_rootName)) {
return this;
}
return new DeserializationConfig(this, rootName);
}
@Override
public DeserializationConfig withView(Class> view) {
return (_view == view) ? this : new DeserializationConfig(this, view);
}
@Override
public DeserializationConfig with(ContextAttributes attrs) {
return (attrs == _attributes) ? this : new DeserializationConfig(this, attrs);
}
/*
/**********************************************************
/* Life-cycle, DeserializationFeature-based factory methods
/**********************************************************
*/
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
*/
public DeserializationConfig with(DeserializationFeature feature)
{
int newDeserFeatures = (_deserFeatures | feature.getMask());
return (newDeserFeatures == _deserFeatures) ? this :
new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
_parserFeatures, _parserFeaturesToChange,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
*/
public DeserializationConfig with(DeserializationFeature first,
DeserializationFeature... features)
{
int newDeserFeatures = _deserFeatures | first.getMask();
for (DeserializationFeature f : features) {
newDeserFeatures |= f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
_parserFeatures, _parserFeaturesToChange,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features enabled.
*/
public DeserializationConfig withFeatures(DeserializationFeature... features)
{
int newDeserFeatures = _deserFeatures;
for (DeserializationFeature f : features) {
newDeserFeatures |= f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
_parserFeatures, _parserFeaturesToChange,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified feature disabled.
*/
public DeserializationConfig without(DeserializationFeature feature)
{
int newDeserFeatures = _deserFeatures & ~feature.getMask();
return (newDeserFeatures == _deserFeatures) ? this :
new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
_parserFeatures, _parserFeaturesToChange,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features disabled.
*/
public DeserializationConfig without(DeserializationFeature first,
DeserializationFeature... features)
{
int newDeserFeatures = _deserFeatures & ~first.getMask();
for (DeserializationFeature f : features) {
newDeserFeatures &= ~f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
_parserFeatures, _parserFeaturesToChange,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/**
* Fluent factory method that will construct and return a new configuration
* object instance with specified features disabled.
*/
public DeserializationConfig withoutFeatures(DeserializationFeature... features)
{
int newDeserFeatures = _deserFeatures;
for (DeserializationFeature f : features) {
newDeserFeatures &= ~f.getMask();
}
return (newDeserFeatures == _deserFeatures) ? this :
new DeserializationConfig(this, _mapperFeatures, newDeserFeatures,
_parserFeatures, _parserFeaturesToChange,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/*
/**********************************************************
/* 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)
{
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);
}
/**
* 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)
{
int newSet = _parserFeatures;
int newMask = _parserFeaturesToChange;
for (JsonParser.Feature f : features) {
int mask = f.getMask();
newSet |= mask;
newMask |= mask;
}
return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this :
new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
newSet, newMask,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/**
* 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)
{
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);
}
/**
* 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)
{
int newSet = _parserFeatures;
int newMask = _parserFeaturesToChange;
for (JsonParser.Feature f : features) {
int mask = f.getMask();
newSet &= ~mask;
newMask |= mask;
}
return ((_parserFeatures == newSet) && (_parserFeaturesToChange == newMask)) ? this :
new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
newSet, newMask,
_formatReadFeatures, _formatReadFeaturesToChange);
}
/*
/**********************************************************
/* 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);
}
/**
* 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;
}
return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
_parserFeatures, _parserFeaturesToChange,
newSet, newMask);
}
/**
* 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);
}
/**
* 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;
}
}
}
return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)
&& (_parserFeatures == parserSet) && (_parserFeaturesToChange == parserMask)
) ? this :
new DeserializationConfig(this, _mapperFeatures, _deserFeatures,
parserSet, parserMask, newSet, newMask);
}
/*
/**********************************************************
/* 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)
* resolve non-fatal deserialization problems.
*/
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));
}
/**
* Method for removing all configured problem handlers; usually done to replace
* existing handler(s) with different one(s)
*/
public DeserializationConfig withNoProblemHandlers() {
if (_problemHandlers == null) {
return this;
}
return new DeserializationConfig(this,
(LinkedNode) null);
}
/*
/**********************************************************
/* JsonParser initialization
/**********************************************************
*/
/**
* 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
*/
public void initialize(JsonParser p) {
if (_parserFeaturesToChange != 0) {
p.overrideStdFeatures(_parserFeatures, _parserFeaturesToChange);
}
if (_formatReadFeaturesToChange != 0) {
p.overrideFormatFeatures(_formatReadFeatures, _formatReadFeaturesToChange);
}
}
/*
/**********************************************************
/* MapperConfig implementation/overrides: other
/**********************************************************
*/
@Override
public boolean useRootWrapping()
{
if (_rootName != null) { // empty String disables wrapping; non-empty enables
return !_rootName.isEmpty();
}
return isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE);
}
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);
}
/**
* 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;
}
/**
* 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;
}
/**
* Bulk access method for getting the bit mask of all {@link DeserializationFeature}s
* that are enabled.
*/
public final int getDeserializationFeatures() {
return _deserFeatures;
}
/**
* Convenience method equivalant to:
*
* isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
*
*
* @since 2.9
*/
public final boolean requiresFullValue() {
return DeserializationFeature.FAIL_ON_TRAILING_TOKENS.enabledIn(_deserFeatures);
}
/*
/**********************************************************
/* Other configuration
/**********************************************************
*/
/**
* Method for getting head of the problem handler chain. May be null,
* if no handlers have been added.
*/
public LinkedNode getProblemHandlers() {
return _problemHandlers;
}
public final JsonNodeFactory getNodeFactory() {
return _nodeFactory;
}
/*
/**********************************************************
/* Introspection methods
/**********************************************************
*/
/**
* Method that will introspect full bean properties for the purpose
* of building a bean deserializer
*
* @param type Type of class to be introspected
*/
@SuppressWarnings("unchecked")
public T introspect(JavaType type) {
return (T) 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);
}
/**
* @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);
}
}
DeserializationContext.java 0000664 0000000 0000000 00000221721 13604243101 0036055 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.IOException;
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.databind.cfg.ContextAttributes;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
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;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.*;
/**
* 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.
*/
public abstract class DeserializationContext
extends DatabindContext
implements java.io.Serializable
{
private static final long serialVersionUID = 1L; // 2.6
/*
/**********************************************************
/* Configuration, immutable
/**********************************************************
*/
/**
* Object that handle details of {@link JsonDeserializer} caching.
*/
protected final DeserializerCache _cache;
/*
/**********************************************************
/* Configuration, changeable via fluent factories
/**********************************************************
*/
/**
* Read-only factory instance; exposed to let
* owners (ObjectMapper
, ObjectReader
)
* access it.
*/
protected final DeserializerFactory _factory;
/*
/**********************************************************
/* Configuration that gets set for instances (not blueprints)
/* (partly denormalized for performance)
/**********************************************************
*/
/**
* Generic deserialization processing configuration
*/
protected final DeserializationConfig _config;
/**
* Bitmap of {@link DeserializationFeature}s that are enabled
*/
protected final int _featureFlags;
/**
* Currently active view, if any.
*/
protected final Class> _view;
/**
* Currently active parser used for deserialization.
* May be different from the outermost parser
* when content is buffered.
*/
protected transient JsonParser _parser;
/**
* Object used for resolving references to injectable
* values.
*/
protected final InjectableValues _injectableValues;
/*
/**********************************************************
/* Per-operation reusable helper objects (not for blueprints)
/**********************************************************
*/
protected transient ArrayBuilders _arrayBuilders;
protected transient ObjectBuffer _objectBuffer;
protected transient DateFormat _dateFormat;
/**
* 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
*/
protected LinkedNode _currentType;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
protected DeserializationContext(DeserializerFactory df) {
this(df, null);
}
protected DeserializationContext(DeserializerFactory df,
DeserializerCache cache)
{
_factory = Objects.requireNonNull(df, "Cannot pass null DeserializerFactory");
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;
_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; }
@Override
public final boolean canOverrideAccessModifiers() {
return _config.canOverrideAccessModifiers();
}
@Override
public final boolean isEnabled(MapperFeature feature) {
return _config.isEnabled(feature);
}
@Override
public final JsonFormat.Value getDefaultPropertyFormat(Class> baseType) {
return _config.getDefaultPropertyFormat(baseType);
}
@Override
public final AnnotationIntrospector getAnnotationIntrospector() {
return _config.getAnnotationIntrospector();
}
@Override
public final TypeFactory getTypeFactory() {
return _config.getTypeFactory();
}
/**
* Method for accessing default Locale to use: convenience method for
*
* getConfig().getLocale();
*
*/
@Override
public Locale getLocale() {
return _config.getLocale();
}
/**
* Method for accessing default TimeZone to use: convenience method for
*
* getConfig().getTimeZone();
*
*/
@Override
public TimeZone getTimeZone() {
return _config.getTimeZone();
}
/*
/**********************************************************
/* Access to per-call state, like generic attributes (2.3+)
/**********************************************************
*/
@Override
public Object getAttribute(Object key) {
return _attributes.getAttribute(key);
}
@Override
public DeserializationContext setAttribute(Object key, Object value)
{
_attributes = _attributes.withPerCallAttribute(key, value);
return this;
}
/**
* Accessor to {@link JavaType} of currently contextualized
* {@link ContextualDeserializer}, 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,
* if process is on-going; null if not.
*/
public JavaType getContextualType() {
return (_currentType == null) ? null : _currentType.value();
}
/*
/**********************************************************
/* Public API, config setting accessors
/**********************************************************
*/
/**
* Method for getting current {@link DeserializerFactory}.
*/
public DeserializerFactory getFactory() {
return _factory;
}
/**
* Convenience method for checking whether specified on/off
* feature is enabled
*/
public final boolean isEnabled(DeserializationFeature feat) {
/* 03-Dec-2010, tatu: minor shortcut; since this is called quite often,
* let's use a local copy of feature settings:
*/
return (_featureFlags & feat.getMask()) != 0;
}
/**
* 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;
}
/**
* Bulk access method for checking that all features specified by
* mask are enabled.
*
* @since 2.3
*/
public final boolean hasDeserializationFeatures(int featureMask) {
return (_featureFlags & featureMask) == 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 (_featureFlags & featureMask) != 0;
}
/**
* Method for accessing the currently active parser.
* May be different from the outermost parser
* when content is buffered.
*
* Use of this method is discouraged: if code has direct access
* to the active parser, that should be used instead.
*/
public final JsonParser getParser() { return _parser; }
public final Object findInjectableValue(Object valueId,
BeanProperty forProperty, Object beanInstance)
throws JsonMappingException
{
if (_injectableValues == null) {
reportBadDefinition(ClassUtil.classOf(valueId), String.format(
"No 'injectableValues' configured, cannot inject value with id [%s]", valueId));
}
return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance);
}
/**
* Convenience method for accessing the default Base64 encoding
* used for decoding base64 encoded binary content.
* Same as calling:
*
* getConfig().getBase64Variant();
*
*/
public final Base64Variant getBase64Variant() {
return _config.getBase64Variant();
}
/**
* Convenience method, functionally equivalent to:
*
* getConfig().getNodeFactory();
*
*/
public final JsonNodeFactory getNodeFactory() {
return _config.getNodeFactory();
}
/*
/**********************************************************
/* Public API, pass-through to DeserializerCache
/**********************************************************
*/
/**
* Method for checking whether we could find a deserializer
* for given type.
*
* @param type
* @since 2.3
*/
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;
}
/**
* Method for finding a value deserializer, and creating a contextual
* version if necessary, for value reached via specified property.
*/
@SuppressWarnings("unchecked")
public final JsonDeserializer findContextualValueDeserializer(JavaType type,
BeanProperty prop) throws JsonMappingException
{
JsonDeserializer deser = _cache.findValueDeserializer(this, _factory, type);
if (deser != null) {
deser = (JsonDeserializer) handleSecondaryContextualization(deser, prop, type);
}
return deser;
}
/**
* Variant that will try to locate deserializer for current type, but without
* 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},
* 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
{
return _cache.findValueDeserializer(this, _factory, type);
}
/**
* Method for finding a deserializer for root-level value.
*/
@SuppressWarnings("unchecked")
public final JsonDeserializer findRootValueDeserializer(JavaType type)
throws JsonMappingException
{
JsonDeserializer deser = _cache.findValueDeserializer(this,
_factory, type);
if (deser == null) { // can this occur?
return null;
}
deser = (JsonDeserializer) handleSecondaryContextualization(deser, null, type);
TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
if (typeDeser != null) {
// important: contextualize to indicate this is for root value
typeDeser = typeDeser.forProperty(null);
return new TypeWrappedDeserializer(typeDeser, deser);
}
return deser;
}
/**
* Convenience method, functionally same as:
*
* getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
*
*/
public final KeyDeserializer findKeyDeserializer(JavaType keyType,
BeanProperty prop) throws JsonMappingException {
KeyDeserializer kd = _cache.findKeyDeserializer(this,
_factory, keyType);
// Second: contextualize?
if (kd instanceof ContextualKeyDeserializer) {
kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop);
}
return kd;
}
/*
/**********************************************************
/* Public API, ObjectId handling
/**********************************************************
*/
/**
* Method called to find and return entry corresponding to given
* Object Id: will add an entry if necessary, and never returns null
*/
public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator> generator, ObjectIdResolver resolver);
/**
* Method called to ensure that every object id encounter during processing
* are resolved.
*
* @throws UnresolvedForwardReference
*/
public abstract void checkUnresolvedObjectId()
throws UnresolvedForwardReference;
/*
/**********************************************************
/* Public API, type handling
/**********************************************************
*/
/**
* Convenience method, functionally equivalent to:
*
* getConfig().constructType(cls);
*
*/
public final JavaType constructType(Class> cls) {
return (cls == null) ? null : _config.constructType(cls);
}
/**
* Helper method that is to be used when resolving basic class name into
* 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
{
// By default, delegate to ClassUtil: can be overridden with custom handling
return getTypeFactory().findClass(className);
}
/*
/**********************************************************
/* Public API, helper object recycling
/**********************************************************
*/
/**
* Method that can be used to get access to a reusable ObjectBuffer,
* useful for efficiently constructing Object arrays and Lists.
* Note that leased buffers should be returned once deserializer
* is done, to allow for reuse during same round of deserialization.
*/
public final ObjectBuffer leaseObjectBuffer()
{
ObjectBuffer buf = _objectBuffer;
if (buf == null) {
buf = new ObjectBuffer();
} else {
_objectBuffer = null;
}
return buf;
}
/**
* Method to call to return object buffer previously leased with
* {@link #leaseObjectBuffer}.
*
* @param buf Returned object buffer
*/
public final void returnObjectBuffer(ObjectBuffer buf)
{
/* Already have a reusable buffer? Let's retain bigger one
* (or if equal, favor newer one, shorter life-cycle)
*/
if (_objectBuffer == null
|| buf.initialCapacity() >= _objectBuffer.initialCapacity()) {
_objectBuffer = buf;
}
}
/**
* Method for accessing object useful for building arrays of
* primitive types (such as int[]).
*/
public final ArrayBuilders getArrayBuilders()
{
if (_arrayBuilders == null) {
_arrayBuilders = new ArrayBuilders();
}
return _arrayBuilders;
}
/*
/**********************************************************
/* Extended API: handler instantiation
/**********************************************************
*/
public abstract JsonDeserializer deserializerInstance(Annotated annotated,
Object deserDef)
throws JsonMappingException;
public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
Object deserDef)
throws JsonMappingException;
/*
/**********************************************************
/* Extended API: resolving contextual deserializers; called
/* 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.
*
* @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) {
_currentType = new LinkedNode(type, _currentType);
try {
deser = ((ContextualDeserializer) deser).createContextual(this, prop);
} finally {
_currentType = _currentType.next();
}
}
return deser;
}
/**
* Method called for secondary property deserializers (ones
* NOT directly created to deal with an annotatable POJO property,
* 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.
* 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) {
_currentType = new LinkedNode(type, _currentType);
try {
deser = ((ContextualDeserializer) deser).createContextual(this, prop);
} finally {
_currentType = _currentType.next();
}
}
return deser;
}
/*
/**********************************************************
/* Parsing methods that may use reusable/-cyclable objects
/**********************************************************
*/
/**
* Convenience method for parsing a Date from given String, using
* currently configured date format (accessed using
* {@link DeserializationConfig#getDateFormat()}).
*
* Implementation will handle thread-safety issues related to
* date formats such that first time this method is called,
* date format is cloned, and cloned instance will be retained
* for use during this deserialization round.
*/
public Date parseDate(String dateStr) throws IllegalArgumentException
{
try {
DateFormat df = getDateFormat();
return df.parse(dateStr);
} catch (ParseException e) {
throw new IllegalArgumentException(String.format(
"Failed to parse Date value '%s': %s", dateStr,
ClassUtil.exceptionMessage(e)));
}
}
/**
* Convenience method for constructing Calendar instance set
* to specified time, to be modified and used by caller.
*/
public Calendar constructCalendar(Date d) {
// 08-Jan-2008, tatu: not optimal, but should work for the most part; let's revise as needed.
Calendar c = Calendar.getInstance(getTimeZone());
c.setTime(d);
return c;
}
/*
/**********************************************************
/* 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 "+ClassUtil.getTypeDescription(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);
if (deser == null) {
return reportBadDefinition(type, String.format(
"Could not find JsonDeserializer for type %s (via property %s)",
ClassUtil.getTypeDescription(type), ClassUtil.nameOf(prop)));
}
return (T) deser.deserialize(p, this);
}
/**
* @since 2.10
*/
public JsonNode readTree(JsonParser p) throws IOException {
JsonToken t = p.currentToken();
if (t == null) {
t = p.nextToken();
if (t == null) {
return getNodeFactory().missingNode();
}
}
if (t == JsonToken.VALUE_NULL) {
return getNodeFactory().nullNode();
}
return (JsonNode) findRootValueDeserializer(_config.constructType(JsonNode.class))
.deserialize(p, this);
}
/*
/**********************************************************
/* Methods for problem handling
/**********************************************************
*/
/**
* Method that deserializers should call if they encounter an unrecognized
* property (and once that is not explicitly designed as ignorable), to
* inform possibly configured {@link DeserializationProblemHandler}s and
* let it handle the problem.
*
* @return True if there was a configured problem handler that was able to handle the
* problem
*/
public boolean handleUnknownProperty(JsonParser p, JsonDeserializer> deser,
Object instanceOrClass, String propName)
throws IOException
{
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
return true;
}
h = h.next();
}
// Nope, not handled. Potentially that's a problem...
if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
p.skipChildren();
return true;
}
// Do we know properties that are expected instead?
Collection propIds = (deser == null) ? null : deser.getKnownPropertyNames();
throw UnrecognizedPropertyException.from(_parser,
instanceOrClass, propName, propIds);
}
/**
* Method that deserializers should call if they encounter a String value
* that cannot be converted to expected key of a {@link java.util.Map}
* valued property.
* Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
* on configured handlers, if any, to allow for recovery; if recovery does not
* succeed, will throw {@link InvalidFormatException} with given message.
*
* @param keyClass Expected type for key
* @param keyValue String value from which to deserialize key
* @param msg Error message template caller wants to use if exception is to be thrown
* @param msgArgs Optional arguments to use for message, if any
*
* @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)
throws IOException
{
// but if not handled, just throw exception
msg = _format(msg, msgArgs);
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
if (key != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if ((key == null) || keyClass.isInstance(key)) {
return key;
}
throw weirdStringException(keyValue, keyClass, String.format(
"DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
ClassUtil.getClassDescription(keyClass),
ClassUtil.getClassDescription(key)
));
}
h = h.next();
}
throw weirdKeyException(keyClass, keyValue, msg);
}
/**
* Method that deserializers should call if they encounter a String value
* that cannot be converted to target property type, in cases where some
* String values could be acceptable (either with different settings,
* or different value).
* Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdStringValue}
* on configured handlers, if any, to allow for recovery; if recovery does not
* succeed, will throw {@link InvalidFormatException} with given message.
*
* @param targetClass Type of property into which incoming number should be converted
* @param value String value from which to deserialize property value
* @param msg Error message template caller wants to use if exception is to be thrown
* @param msgArgs Optional arguments to use for message, if any
*
* @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)
throws IOException
{
// but if not handled, just throw exception
msg = _format(msg, msgArgs);
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
Object instance = h.value().handleWeirdStringValue(this, targetClass, value, msg);
if (instance != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if (_isCompatible(targetClass, instance)) {
return instance;
}
throw weirdStringException(value, targetClass, String.format(
"DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
ClassUtil.getClassDescription(targetClass),
ClassUtil.getClassDescription(instance)
));
}
h = h.next();
}
throw weirdStringException(value, targetClass, msg);
}
/**
* Method that deserializers should call if they encounter a numeric value
* that cannot be converted to target property type, in cases where some
* numeric values could be acceptable (either with different settings,
* or different numeric value).
* Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
* on configured handlers, if any, to allow for recovery; if recovery does not
* succeed, will throw {@link InvalidFormatException} with given message.
*
* @param targetClass Type of property into which incoming number should be converted
* @param value Number value from which to deserialize property value
* @param msg Error message template caller wants to use if exception is to be thrown
* @param msgArgs Optional arguments to use for message, if any
*
* @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)
throws IOException
{
msg = _format(msg, msgArgs);
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
Object key = h.value().handleWeirdNumberValue(this, targetClass, value, msg);
if (key != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if (_isCompatible(targetClass, key)) {
return key;
}
throw weirdNumberException(value, targetClass, _format(
"DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s",
ClassUtil.getClassDescription(targetClass),
ClassUtil.getClassDescription(key)
));
}
h = h.next();
}
throw weirdNumberException(value, targetClass, msg);
}
public Object handleWeirdNativeValue(JavaType targetType, Object badValue,
JsonParser p)
throws IOException
{
LinkedNode h = _config.getProblemHandlers();
final Class> raw = targetType.getRawClass();
for (; h != null; h = h.next()) {
// Can bail out if it's handled
Object goodValue = h.value().handleWeirdNativeValue(this, targetType, badValue, p);
if (goodValue != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if ((goodValue == null) || raw.isInstance(goodValue)) {
return goodValue;
}
throw JsonMappingException.from(p, _format(
"DeserializationProblemHandler.handleWeirdNativeValue() for type %s returned value of type %s",
ClassUtil.getClassDescription(targetType),
ClassUtil.getClassDescription(goodValue)
));
}
}
throw weirdNativeValueException(badValue, raw);
}
/**
* Method that deserializers should call if they fail to instantiate value
* due to lack of viable instantiator (usually creator, that is, constructor
* or static factory method). Method should be called at point where value
* has not been decoded, so that handler has a chance to handle decoding
* using alternate mechanism, and handle underlying content (possibly by
* just skipping it) to keep input state valid
*
* @param instClass Type that was to be instantiated
* @param valueInst (optional) Value instantiator to be used, if any; null if type does not
* use one for instantiation (custom deserialiers don't; standard POJO deserializer does)
* @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,
JsonParser p, String msg, Object... msgArgs)
throws IOException
{
if (p == null) {
p = getParser();
}
msg = _format(msg, msgArgs);
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
Object instance = h.value().handleMissingInstantiator(this,
instClass, valueInst, p, msg);
if (instance != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if (_isCompatible(instClass, instance)) {
return instance;
}
reportBadDefinition(constructType(instClass), String.format(
"DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s",
ClassUtil.getClassDescription(instClass),
ClassUtil.getClassDescription((instance)
)));
}
h = h.next();
}
// 16-Oct-2016, tatu: This is either a definition problem (if no applicable creator
// 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",
ClassUtil.nameOf(instClass), msg);
return reportBadDefinition(constructType(instClass), msg);
}
msg = String.format("Cannot construct instance of %s (although at least one Creator exists): %s",
ClassUtil.nameOf(instClass), msg);
return reportInputMismatch(instClass, msg);
}
/**
* Method that deserializers should call if they fail to instantiate value
* due to an exception that was thrown by constructor (or other mechanism used
* to create instances).
* Default implementation will try to call {@link DeserializationProblemHandler#handleInstantiationProblem}
* on configured handlers, if any, to allow for recovery; if recovery does not
* succeed, will throw exception constructed with {@link #instantiationException}.
*
* @param instClass Type that was to be instantiated
* @param argument (optional) Argument that was passed to constructor or equivalent
* instantiator; often a {@link java.lang.String}.
* @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)
throws IOException
{
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
Object instance = h.value().handleInstantiationProblem(this, instClass, argument, t);
if (instance != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if (_isCompatible(instClass, instance)) {
return instance;
}
reportBadDefinition(constructType(instClass), String.format(
"DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s",
ClassUtil.getClassDescription(instClass),
ClassUtil.classNameOf(instance)
));
}
h = h.next();
}
// 18-May-2016, tatu: Only wrap if not already a valid type to throw
ClassUtil.throwIfIOE(t);
// [databind#2164]: but see if wrapping is desired
if (!isEnabled(DeserializationFeature.WRAP_EXCEPTIONS)) {
ClassUtil.throwIfRTE(t);
}
throw instantiationException(instClass, t);
}
/**
* Method that deserializers should call if the first token of the value to
* deserialize is of unexpected type (that is, type of token that deserializer
* cannot handle). This could occur, for example, if a Number deserializer
* encounter {@link JsonToken#START_ARRAY} instead of
* {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
*
* @param instClass Type that was to be instantiated
* @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(constructType(instClass), p.getCurrentToken(), p, null);
}
/**
* Method that deserializers should call if the first token of the value to
* deserialize is of unexpected type (that is, type of token that deserializer
* cannot handle). This could occur, for example, if a Number deserializer
* encounter {@link JsonToken#START_ARRAY} instead of
* {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
*
* @param instClass Type that was to be instantiated
* @param t Token encountered that does match expected
* @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)
throws IOException
{
return handleUnexpectedToken(constructType(instClass), t, p, msg, msgArgs);
}
/**
* Method that deserializers should call if the first token of the value to
* deserialize is of unexpected type (that is, type of token that deserializer
* cannot handle). This could occur, for example, if a Number deserializer
* encounter {@link JsonToken#START_ARRAY} instead of
* {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
*
* @param targetType Type that was to be instantiated
* @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.10
*/
public Object handleUnexpectedToken(JavaType targetType, JsonParser p)
throws IOException
{
return handleUnexpectedToken(targetType, p.getCurrentToken(), p, null);
}
/**
* Method that deserializers should call if the first token of the value to
* deserialize is of unexpected type (that is, type of token that deserializer
* cannot handle). This could occur, for example, if a Number deserializer
* encounter {@link JsonToken#START_ARRAY} instead of
* {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
*
* @param targetType Type that was to be instantiated
* @param t Token encountered that does match expected
* @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.10
*/
public Object handleUnexpectedToken(JavaType targetType, JsonToken t,
JsonParser p, String msg, Object... msgArgs)
throws IOException
{
msg = _format(msg, msgArgs);
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
Object instance = h.value().handleUnexpectedToken(this,
targetType, t, p, msg);
if (instance != DeserializationProblemHandler.NOT_HANDLED) {
if (_isCompatible(targetType.getRawClass(), instance)) {
return instance;
}
reportBadDefinition(targetType, String.format(
"DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s",
ClassUtil.getClassDescription(targetType),
ClassUtil.classNameOf(instance)
));
}
h = h.next();
}
if (msg == null) {
if (t == null) {
msg = String.format("Unexpected end-of-input when binding data into %s",
ClassUtil.getTypeDescription(targetType));
} else {
msg = String.format("Cannot deserialize instance of %s out of %s token",
ClassUtil.getTypeDescription(targetType), t);
}
}
reportInputMismatch(targetType, msg);
return null; // never gets here
}
/**
* Method that deserializers should call if they encounter a type id
* (for polymorphic deserialization) that cannot be resolved to an
* actual type; usually since there is no mapping defined.
* Default implementation will try to call {@link DeserializationProblemHandler#handleUnknownTypeId}
* on configured handlers, if any, to allow for recovery; if recovery does not
* succeed, will throw exception constructed with {@link #invalidTypeIdException}.
*
* @param baseType Base type from which resolution starts
* @param id Type id that could not be converted
* @param extraDesc Additional problem description to add to default exception message,
* if resolution fails.
*
* @return {@link JavaType} that id resolves to
*
* @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
{
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
JavaType type = h.value().handleUnknownTypeId(this, baseType, id, idResolver, extraDesc);
if (type != null) {
if (type.hasRawClass(Void.class)) {
return null;
}
// But ensure there's type compatibility
if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
return type;
}
throw invalidTypeIdException(baseType, id,
"problem handler tried to resolve into non-subtype: "+
ClassUtil.getTypeDescription(type));
}
h = h.next();
}
// 24-May-2016, tatu: Actually we may still not want to fail quite yet
if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
return null;
}
throw invalidTypeIdException(baseType, id, extraDesc);
}
/**
* @since 2.9
*/
public JavaType handleMissingTypeId(JavaType baseType,
TypeIdResolver idResolver, String extraDesc) throws IOException
{
LinkedNode h = _config.getProblemHandlers();
while (h != null) {
// Can bail out if it's handled
JavaType type = h.value().handleMissingTypeId(this, baseType, idResolver, extraDesc);
if (type != null) {
if (type.hasRawClass(Void.class)) {
return null;
}
// But ensure there's type compatibility
if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
return type;
}
throw invalidTypeIdException(baseType, null,
"problem handler tried to resolve into non-subtype: "+
ClassUtil.getTypeDescription(type));
}
h = h.next();
}
// 09-Mar-2017, tatu: We may want to consider yet another feature at some
// point to allow returning `null`... but that seems bit risky for now
// if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
// return null;
// }
throw missingTypeIdException(baseType, extraDesc);
}
/**
* Method that deserializer may call if it is called to do an update ("merge")
* but deserializer operates on a non-mergeable type. Although this should
* usually be caught earlier, sometimes it may only be caught during operation
* and if so this is the method to call.
* 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.10
*/
public void handleBadMerge(JsonDeserializer> deser) throws JsonMappingException
{
if (!isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
JavaType type = constructType(deser.handledType());
String msg = String.format("Invalid configuration: values of type %s cannot be merged",
ClassUtil.getTypeDescription(type));
throw InvalidDefinitionException.from(getParser(), msg, type);
}
}
/**
* @since 2.9.2
*/
protected boolean _isCompatible(Class> target, Object value)
{
if ((value == null) || target.isInstance(value)) {
return true;
}
// [databind#1767]: Make sure to allow wrappers for primitive fields
return target.isPrimitive()
&& ClassUtil.wrapperType(target).isInstance(value);
}
/*
/**********************************************************
/* Methods for problem reporting, in cases where recovery
/* is not considered possible: input problem
/**********************************************************
*/
/**
* Method for deserializers to call
* when the token encountered was of type different than what should
* be seen at that position, usually within a sequence of expected tokens.
* 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)
throws JsonMappingException
{
msg = _format(msg, msgArgs);
throw wrongTokenException(getParser(), deser.handledType(), expToken, msg);
}
/**
* Method for deserializers to call
* when the token encountered was of type different than what should
* be seen at that position, usually within a sequence of expected tokens.
* 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)
throws JsonMappingException
{
msg = _format(msg, msgArgs);
throw wrongTokenException(getParser(), targetType, expToken, msg);
}
/**
* Method for deserializers to call
* when the token encountered was of type different than what should
* be seen at that position, usually within a sequence of expected tokens.
* 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)
throws JsonMappingException
{
msg = _format(msg, msgArgs);
throw wrongTokenException(getParser(), targetType, expToken, msg);
}
/**
* @since 2.8
*/
public T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
throws JsonMappingException
{
String msg = String.format("No Object Id found for an instance of %s, to assign to property '%s'",
ClassUtil.classNameOf(bean), oidReader.propertyName);
return reportInputMismatch(oidReader.idProperty, msg);
}
/**
* 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
{
msg = _format(msg, msgArgs);
throw MismatchedInputException.from(getParser(), src.handledType(), msg);
}
/**
* 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
{
msg = _format(msg, msgArgs);
throw MismatchedInputException.from(getParser(), targetType, msg);
}
/**
* 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
{
msg = _format(msg, msgArgs);
throw MismatchedInputException.from(getParser(), targetType, msg);
}
/**
* 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
{
msg = _format(msg, msgArgs);
JavaType type = (prop == null) ? null : prop.getType();
final MismatchedInputException e = MismatchedInputException.from(getParser(), type, msg);
// [databind#2357]: Include property name, if we have it
if (prop != null) {
AnnotatedMember member = prop.getMember();
if (member != null) {
e.prependPath(member.getDeclaringClass(), prop.getName());
}
}
throw e;
}
/**
* Helper method used to indicate a problem with input in cases where more
* specific reportXxx()
method was not available.
*
* @since 2.10
*/
public T reportPropertyInputMismatch(Class> targetType, String propertyName,
String msg, Object... msgArgs) throws JsonMappingException
{
msg = _format(msg, msgArgs);
MismatchedInputException e = MismatchedInputException.from(getParser(), targetType, msg);
if (propertyName != null) {
e.prependPath(targetType, propertyName);
}
throw e;
}
/**
* Helper method used to indicate a problem with input in cases where more
* specific reportXxx()
method was not available.
*
* @since 2.10
*/
public T reportPropertyInputMismatch(JavaType targetType, String propertyName,
String msg, Object... msgArgs) throws JsonMappingException
{
return reportPropertyInputMismatch(targetType.getRawClass(), propertyName, msg, msgArgs);
}
public T reportTrailingTokens(Class> targetType,
JsonParser p, JsonToken trailingToken) throws JsonMappingException
{
throw MismatchedInputException.from(p, targetType, String.format(
"Trailing token (of type %s) found after value (bound as %s): not allowed as per `DeserializationFeature.FAIL_ON_TRAILING_TOKENS`",
trailingToken, ClassUtil.nameOf(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
/* is not considered possible: POJO definition problems
/**********************************************************
*/
/**
* 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 {
msg = _format(msg, msgArgs);
String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
msg = String.format("Invalid type definition for type %s: %s", beanDesc, msg);
throw InvalidDefinitionException.from(_parser, msg, bean, null);
}
/**
* 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 {
msg = _format(msg, msgArgs);
String propName = ClassUtil.nameOf(prop);
String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
msg = String.format("Invalid definition for property %s (of type %s): %s",
propName, beanDesc, msg);
throw InvalidDefinitionException.from(_parser, msg, bean, prop);
}
@Override
public T reportBadDefinition(JavaType type, String msg) throws JsonMappingException {
throw InvalidDefinitionException.from(_parser, msg, type);
}
/**
* @deprecated Since 2.10 use {@link #handleBadMerge} instead
*/
@Deprecated // since 2.10
public T reportBadMerge(JsonDeserializer> deser) throws JsonMappingException {
handleBadMerge(deser);
return null;
}
/*
/**********************************************************
/* Methods for constructing semantic exceptions; usually not
/* to be called directly, call `handleXxx()` instead
/**********************************************************
*/
/**
* Helper method for constructing {@link JsonMappingException} to indicate
* that the token encountered was of type different than what should
* be seen at that position, usually within a sequence of expected tokens.
* 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);
msg = _colonConcat(msg, extra);
return MismatchedInputException.from(p, targetType, msg);
}
public JsonMappingException wrongTokenException(JsonParser p, Class> targetType,
JsonToken expToken, String extra)
{
String msg = String.format("Unexpected token (%s), expected %s",
p.getCurrentToken(), 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
* Object field name was not in format to be able to deserialize specified
* key type.
* Note that most of the time this method should NOT be called; instead,
* {@link #handleWeirdKey} should be called which will call this method
* if necessary.
*/
public JsonMappingException weirdKeyException(Class> keyClass, String keyValue,
String msg) {
return InvalidFormatException.from(_parser,
String.format("Cannot deserialize Map key of type %s from String %s: %s",
ClassUtil.nameOf(keyClass), _quotedString(keyValue), msg),
keyValue, keyClass);
}
/**
* Helper method for constructing exception to indicate that input JSON
* String was not suitable for deserializing into given target type.
* Note that most of the time this method should NOT be called; instead,
* {@link #handleWeirdStringValue} should be called which will call this method
* if necessary.
*
* @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) {
final String msg = String.format("Cannot deserialize value of type %s from String %s: %s",
ClassUtil.nameOf(instClass), _quotedString(value), msgBase);
return InvalidFormatException.from(_parser, msg, value, instClass);
}
/**
* Helper method for constructing exception to indicate that input JSON
* Number was not suitable for deserializing into given target type.
* Note that most of the time this method should NOT be called; instead,
* {@link #handleWeirdNumberValue} should be called which will call this method
* if necessary.
*/
public JsonMappingException weirdNumberException(Number value, Class> instClass,
String msg) {
return InvalidFormatException.from(_parser,
String.format("Cannot deserialize value of type %s from number %s: %s",
ClassUtil.nameOf(instClass), String.valueOf(value), msg),
value, instClass);
}
/**
* Helper method for constructing exception to indicate that input JSON
* token of type "native value" (see {@link JsonToken#VALUE_EMBEDDED_OBJECT})
* is of incompatible type (and there is no delegating creator or such to use)
* 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)
{
return InvalidFormatException.from(_parser, String.format(
"Cannot deserialize value of type %s from native value (`JsonToken.VALUE_EMBEDDED_OBJECT`) of type %s: incompatible types",
ClassUtil.nameOf(instClass), ClassUtil.classNameOf(value)),
value, instClass);
}
/**
* Helper method for constructing instantiation exception for specified type,
* to indicate problem with physically constructing instance of
* specified class (missing constructor, exception from constructor)
*
* Note that most of the time this method should NOT be called directly; instead,
* {@link #handleInstantiationProblem} should be called which will call this method
* if necessary.
*/
public JsonMappingException instantiationException(Class> instClass, Throwable cause) {
String excMsg;
if (cause == null) {
excMsg = "N/A";
} else if ((excMsg = ClassUtil.exceptionMessage(cause)) == null) {
excMsg = ClassUtil.nameOf(cause.getClass());
}
String msg = String.format("Cannot construct instance of %s, problem: %s",
ClassUtil.nameOf(instClass), excMsg);
// [databind#2162]: use specific exception type as we don't know if it's
// due to type definition, input, or neither
return ValueInstantiationException.from(_parser, msg, constructType(instClass), cause);
}
/**
* Helper method for constructing instantiation exception for specified type,
* to indicate that instantiation failed due to missing instantiator
* (creator; constructor or factory method).
*
* Note that most of the time this method should NOT be called; instead,
* {@link #handleMissingInstantiator} should be called which will call this method
* if necessary.
*/
public JsonMappingException instantiationException(Class> instClass, String msg0) {
// [databind#2162]: use specific exception type as we don't know if it's
// due to type definition, input, or neither
return ValueInstantiationException.from(_parser,
String.format("Cannot construct instance of %s: %s",
ClassUtil.nameOf(instClass), msg0),
constructType(instClass));
}
@Override
public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
String extraDesc) {
String msg = String.format("Could not resolve type id '%s' as a subtype of %s",
typeId, ClassUtil.getTypeDescription(baseType));
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",
baseType);
return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, null);
}
/*
/**********************************************************
/* 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, ClassUtil.getTypeDescription(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
*/
@Deprecated
public JsonMappingException mappingException(Class> targetClass) {
return mappingException(targetClass, _parser.getCurrentToken());
}
/**
* @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
*/
@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.
*/
DateFormat df = _config.getDateFormat();
_dateFormat = df = (DateFormat) df.clone();
return df;
}
}
DeserializationFeature.java 0000664 0000000 0000000 00000052630 13604243101 0036025 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import com.fasterxml.jackson.databind.cfg.ConfigFeature;
/**
* Enumeration that defines simple on/off features that affect
* the way Java objects are deserialized from JSON
*
* Note that features can be set both through
* {@link ObjectMapper} (as sort of defaults) and through
* {@link ObjectReader}.
* In first case these defaults must follow "config-then-use" patterns
* (i.e. defined once, not changed afterwards); all per-call
* changes must be done using {@link ObjectReader}.
*
* Note that features that do not indicate version of inclusion
* were available in Jackson 2.0 (or earlier); only later additions
* indicate version of inclusion.
*/
public enum DeserializationFeature implements ConfigFeature
{
/*
/******************************************************
/* Value (mostly scalar) conversion features
/******************************************************
*/
/**
* Feature that determines whether JSON floating point numbers
* are to be deserialized into {@link java.math.BigDecimal}s
* if only generic type description (either {@link Object} or
* {@link Number}, or within untyped {@link java.util.Map}
* or {@link java.util.Collection} context) is available.
* If enabled such values will be deserialized as {@link java.math.BigDecimal}s;
* if disabled, will be deserialized as {@link Double}s.
*
* NOTE: one aspect of {@link java.math.BigDecimal} handling that may need
* configuring is whether trailing zeroes are trimmed:
* {@link com.fasterxml.jackson.databind.node.JsonNodeFactory} has
* {@link com.fasterxml.jackson.databind.node.JsonNodeFactory#withExactBigDecimals} for
* changing default behavior (default is for trailing zeroes to be trimmed).
*
* Feature is disabled by default, meaning that "untyped" floating
* point numbers will by default be deserialized as {@link Double}s
* (choice is for performance reason -- BigDecimals are slower than
* Doubles).
*/
USE_BIG_DECIMAL_FOR_FLOATS(false),
/**
* Feature that determines whether JSON integral (non-floating-point)
* numbers are to be deserialized into {@link java.math.BigInteger}s
* if only generic type description (either {@link Object} or
* {@link Number}, or within untyped {@link java.util.Map}
* or {@link java.util.Collection} context) is available.
* If enabled such values will be deserialized as
* {@link java.math.BigInteger}s;
* if disabled, will be deserialized as "smallest" available type,
* which is either {@link Integer}, {@link Long} or
* {@link java.math.BigInteger}, depending on number of digits.
*
* Feature is disabled by default, meaning that "untyped" integral
* numbers will by default be deserialized using whatever
* is the most compact integral type, to optimize efficiency.
*/
USE_BIG_INTEGER_FOR_INTS(false),
/**
* Feature that determines how "small" JSON integral (non-floating-point)
* numbers -- ones that fit in 32-bit signed integer (`int`) -- are bound
* when target type is loosely typed as {@link Object} or {@link Number}
* (or within untyped {@link java.util.Map} or {@link java.util.Collection} context).
* If enabled, such values will be deserialized as {@link java.lang.Long};
* if disabled, they will be deserialized as "smallest" available type,
* {@link Integer}.
* In addition, if enabled, trying to bind values that do not fit in {@link java.lang.Long}
* will throw a {@link com.fasterxml.jackson.core.JsonProcessingException}.
*
* Note: if {@link #USE_BIG_INTEGER_FOR_INTS} is enabled, it has precedence
* over this setting, forcing use of {@link java.math.BigInteger} for all
* integral values.
*
* 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),
/**
* Feature that determines whether JSON Array is mapped to
* Object[]
or List<Object>
when binding
* "untyped" objects (ones with nominal type of java.lang.Object
).
* If true, binds as Object[]
; if false, as List<Object>
.
*
* Feature is disabled by default, meaning that JSON arrays are bound as
* {@link java.util.List}s.
*/
USE_JAVA_ARRAY_FOR_JSON_ARRAY(false),
/*
/******************************************************
/* Error handling features
/******************************************************
*/
/**
* Feature that determines whether encountering of unknown
* properties (ones that do not map to a property, and there is
* no "any setter" or handler that can handle it)
* should result in a failure (by throwing a
* {@link JsonMappingException}) or not.
* This setting only takes effect after all other handling
* methods for unknown properties have been tried, and
* property remains unhandled.
*
* Feature is enabled by default (meaning that a
* {@link JsonMappingException} will be thrown if an unknown property
* is encountered).
*/
FAIL_ON_UNKNOWN_PROPERTIES(true),
/**
* Feature that determines whether encountering of JSON null
* is an error when deserializing into Java primitive types
* (like 'int' or 'double'). If it is, a JsonProcessingException
* is thrown to indicate this; if not, default value is used
* (0 for 'int', 0.0 for double, same defaulting as what JVM uses).
*
* Feature is disabled by default.
*/
FAIL_ON_NULL_FOR_PRIMITIVES(false),
/**
* Feature that determines whether JSON integer numbers are valid
* values to be used for deserializing Java enum values.
* If set to 'false' numbers are acceptable and are used to map to
* ordinal() of matching enumeration value; if 'true', numbers are
* not allowed and a {@link JsonMappingException} will be thrown.
* Latter behavior makes sense if there is concern that accidental
* mapping from integer values to enums might happen (and when enums
* are always serialized as JSON Strings)
*
* Feature is disabled by default.
*/
FAIL_ON_NUMBERS_FOR_ENUMS(false),
/**
* Feature that determines what happens when type of a polymorphic
* value (indicated for example by {@link com.fasterxml.jackson.annotation.JsonTypeInfo})
* cannot be found (missing) or resolved (invalid class name, unmappable id);
* if enabled, an exception ir thrown; if false, null value is used instead.
*
* Feature is enabled by default so that exception is thrown for missing or invalid
* type information.
*
* @since 2.2
*/
FAIL_ON_INVALID_SUBTYPE(true),
/**
* Feature that determines what happens when reading JSON content into tree
* ({@link com.fasterxml.jackson.core.TreeNode}) and a duplicate key
* is encountered (property name that was already seen for the JSON Object).
* If enabled, {@link JsonMappingException} will be thrown; if disabled, no exception
* is thrown and the new (later) value overwrites the earlier value.
*
* Note that this property does NOT affect other aspects of data-binding; that is,
* no detection is done with respect to POJO properties or {@link java.util.Map}
* 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),
/**
* Feature that determines what happens when a property that has been explicitly
* marked as ignorable is encountered in input: if feature is enabled,
* {@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),
/**
* Feature that determines what happens if an Object Id reference is encountered
* that does not refer to an actual Object with that id ("unresolved Object Id"):
* either an exception is thrown (true
), or a null object is used
* instead (false
).
* Note that if this is set to false
, no further processing is done;
* specifically, if reference is defined via setter method, that method will NOT
* be called.
*
* 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),
/**
* Feature that determines what happens if one or more Creator properties (properties
* bound to parameters of Creator method (constructor or static factory method))
* are missing value to bind to from content.
* If enabled, such missing values result in a {@link JsonMappingException} being
* thrown with information on the first one (by index) of missing properties.
* If disabled, and if property is NOT marked as required,
* missing Creator properties are filled
* with null values
provided by deserializer for the type of parameter
* (usually null for Object types, and default value for primitives; but redefinable
* via custom deserializers).
*
* Note that having an injectable value counts as "not missing".
*
* 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),
/**
* Feature that determines what happens if one or more Creator properties (properties
* bound to parameters of Creator method (constructor or static factory method))
* are bound to null values - either from the JSON or as a default value. This
* is useful if you want to avoid nulls in your codebase, and particularly useful
* 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),
/**
* Feature that determines what happens when a property annotated with
* {@link com.fasterxml.jackson.annotation.JsonTypeInfo.As#EXTERNAL_PROPERTY} is missing,
* but associated type id is available. If enabled, {@link JsonMappingException} is always
* thrown when property value is missing (if type id does exist);
* if disabled, exception is only thrown if property is marked as `required`.
*
* 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),
/**
* Feature that determines behaviour for data-binding after binding the root value.
* If feature is enabled, one more call to
* {@link com.fasterxml.jackson.core.JsonParser#nextToken} is made to ensure that
* no more tokens are found (and if any is found,
* {@link com.fasterxml.jackson.databind.exc.MismatchedInputException} is thrown); if
* disabled, no further checks are made.
*
* Feature could alternatively be called READ_FULL_STREAM
, since it
* effectively verifies that input stream contains only as much data as is needed
* for binding the full value, and nothing more (except for possible ignorable
* white space or comments, if supported by data format).
*
* 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),
/**
* Feature that determines whether Jackson code should catch
* and wrap {@link Exception}s (but never {@link Error}s!)
* to add additional information about
* location (within input) of problem or not. If enabled,
* most exceptions will be caught and re-thrown (exception
* specifically being that {@link java.io.IOException}s may be passed
* as is, since they are declared as throwable); this can be
* convenient both in that all exceptions will be checked and
* declared, and so there is more contextual information.
* However, sometimes calling application may just want "raw"
* unchecked exceptions passed as is.
*
* Feature is enabled by default.
*/
WRAP_EXCEPTIONS(true),
/*
/******************************************************
/* Structural conversion features
/******************************************************
*/
/**
* Feature that determines whether it is acceptable to coerce non-array
* (in JSON) values to work with Java collection (arrays, java.util.Collection)
* types. If enabled, collection deserializers will try to handle non-array
* values as if they had "implicit" surrounding JSON array.
* This feature is meant to be used for compatibility/interoperability reasons,
* to work with packages (such as XML-to-JSON converters) that leave out JSON
* array in cases where there is just a single element in array.
*
* Feature is disabled by default.
*/
ACCEPT_SINGLE_VALUE_AS_ARRAY(false),
/**
* Feature that determines whether it is acceptable to coerce single value array (in JSON)
* values to the corresponding value type. This is basically the opposite of the {@link #ACCEPT_SINGLE_VALUE_AS_ARRAY}
* feature. If more than one value is found in the array, a JsonMappingException is thrown.
*
*
* Feature is disabled by default
* @since 2.4
*/
UNWRAP_SINGLE_VALUE_ARRAYS(false),
/**
* Feature to allow "unwrapping" root-level JSON value, to match setting of
* {@link SerializationFeature#WRAP_ROOT_VALUE} used for serialization.
* Will verify that the root JSON value is a JSON Object, and that it has
* a single property with expected root name. If not, a
* {@link JsonMappingException} is thrown; otherwise value of the wrapped property
* will be deserialized as if it was the root value.
*
* Feature is disabled by default.
*/
UNWRAP_ROOT_VALUE(false),
/*
/******************************************************
/* Value conversion features
/******************************************************
*/
/**
* Feature that can be enabled to allow JSON empty String
* value ("") to be bound as `null` for POJOs and other structured
* values ({@link java.util.Map}s, {@link java.util.Collection}s).
* If disabled, standard POJOs can only be bound from JSON `null` or
* JSON Object (standard meaning that no custom deserializers or
* constructors are defined; both of which can add support for other
* kinds of JSON values); if enabled, empty JSON String can be taken
* to be equivalent of JSON null.
*
* 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}.
*
* Feature is disabled by default.
*/
ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false),
/**
* Feature that can be enabled to allow empty JSON Array
* value (that is, [ ]
) to be bound to POJOs (and
* with 2.9, other values too) as `null`.
* If disabled, standard POJOs can only be bound from JSON `null` or
* JSON Object (standard meaning that no custom deserializers or
* constructors are defined; both of which can add support for other
* kinds of JSON values); if enabled, empty JSON Array will be taken
* to be equivalent of JSON null.
*
* Feature is disabled by default.
*
* @since 2.5
*/
ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false),
/**
* Feature that determines whether coercion from JSON floating point
* number (anything with command (`.`) or exponent portion (`e` / `E'))
* to an expected integral number (`int`, `long`, `java.lang.Integer`, `java.lang.Long`,
* `java.math.BigDecimal`) is allowed or not.
* If enabled, coercion truncates value; if disabled, a {@link JsonMappingException}
* will be thrown.
*
* Feature is enabled by default.
*
* @since 2.6
*/
ACCEPT_FLOAT_AS_INT(true),
/**
* Feature that determines standard deserialization mechanism used for
* Enum values: if enabled, Enums are assumed to have been serialized using
* return value of Enum.toString()
;
* if disabled, return value of Enum.name()
is assumed to have been used.
*
* Note: this feature should usually have same value
* as {@link SerializationFeature#WRITE_ENUMS_USING_TO_STRING}.
*
* Feature is disabled by default.
*/
READ_ENUMS_USING_TO_STRING(false),
/**
* Feature that allows unknown Enum values to be parsed as null values.
* If disabled, unknown Enum values will throw exceptions.
*
* Note that in some cases this will basically ignore unknown Enum values;
* this is the keys for keys of {@link java.util.EnumMap} and values
* of {@link java.util.EnumSet} (because nulls are not accepted in these
* cases).
*
* Feature is disabled by default.
*
* @since 2.0
*/
READ_UNKNOWN_ENUM_VALUES_AS_NULL(false),
/**
* Feature that allows unknown Enum values to be ignored and a predefined value specified through
* {@link com.fasterxml.jackson.annotation.JsonEnumDefaultValue @JsonEnumDefaultValue} annotation.
* If disabled, unknown Enum values will throw exceptions.
* 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),
/**
* Feature that controls whether numeric timestamp values are expected
* to be written using nanosecond timestamps (enabled) or not (disabled),
* if and only if datatype supports such resolution.
* Only newer datatypes (such as Java8 Date/Time) support such resolution --
* older types (pre-Java8 java.util.Date etc) and Joda do not --
* and this setting has no effect on such types.
*
* If disabled, standard millisecond timestamps are assumed.
* 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),
/**
* Feature that specifies whether context provided {@link java.util.TimeZone}
* ({@link DeserializationContext#getTimeZone()} should be used to adjust Date/Time
* values on deserialization, even if value itself contains timezone information.
* If enabled, contextual TimeZone
will essentially override any other
* TimeZone information; if disabled, it will only be used if value itself does not
* contain any TimeZone information.
*
* Note that exact behavior depends on date/time types in question; and specifically
* JDK type of {@link java.util.Date} does NOT have in-built timezone information
* so this setting has no effect.
* Further, while {@link java.util.Calendar} does have this information basic
* JDK {@link java.text.SimpleDateFormat} is unable to retain parsed zone information,
* and as a result, {@link java.util.Calendar} will always get context timezone
* adjustment regardless of this setting.
*
*
* 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
/******************************************************
*/
/**
* Feature that determines whether {@link ObjectReader} should
* try to eagerly fetch necessary {@link JsonDeserializer} when
* possible. This improves performance in cases where similarly
* configured {@link ObjectReader} instance is used multiple
* times; and should not significantly affect single-use cases.
*
* Note that there should not be any need to normally disable this
* feature: only consider that if there are actual perceived problems.
*
* Feature is enabled by default.
*
* @since 2.1
*/
EAGER_DESERIALIZER_FETCH(true)
;
private final boolean _defaultState;
private final int _mask;
private DeserializationFeature(boolean defaultState) {
_defaultState = defaultState;
_mask = (1 << ordinal());
}
@Override
public boolean enabledByDefault() { return _defaultState; }
@Override
public int getMask() { return _mask; }
@Override
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
}
InjectableValues.java 0000664 0000000 0000000 00000006107 13604243101 0034601 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.util.*;
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Abstract class that defines API for objects that provide value to
* "inject" during deserialization. An instance of this object
*/
public abstract class InjectableValues
{
/**
* Method called to find value identified by id valueId
to
* inject as value of specified property during deserialization, passing
* POJO instance in which value will be injected if it is available
* (will be available when injected via field or setter; not available
* when injected via constructor or factory method argument).
*
* @param valueId Object that identifies value to inject; may be a simple
* name or more complex identifier object, whatever provider needs
* @param ctxt Deserialization context
* @param forProperty Bean property in which value is to be injected
* @param beanInstance Bean instance that contains property to inject,
* if available; null if bean has not yet been constructed.
*/
public abstract Object findInjectableValue(Object valueId, DeserializationContext ctxt,
BeanProperty forProperty, Object beanInstance) throws JsonMappingException;
/*
/**********************************************************
/* Standard implementation
/**********************************************************
*/
/**
* Simple standard implementation which uses a simple Map to
* store values to inject, identified by simple String keys.
*/
public static class Std
extends InjectableValues
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
protected final Map _values;
public Std() {
this(new HashMap());
}
public Std(Map values) {
_values = values;
}
public Std addValue(String key, Object value) {
_values.put(key, value);
return this;
}
public Std addValue(Class> classKey, Object value) {
_values.put(classKey.getName(), value);
return this;
}
@Override
public Object findInjectableValue(Object valueId, DeserializationContext ctxt,
BeanProperty forProperty, Object beanInstance) throws JsonMappingException
{
if (!(valueId instanceof String)) {
ctxt.reportBadDefinition(ClassUtil.classOf(valueId),
String.format(
"Unrecognized inject value id type (%s), expecting String",
ClassUtil.classNameOf(valueId)));
}
String key = (String) valueId;
Object ob = _values.get(key);
if (ob == null && !_values.containsKey(key)) {
throw new IllegalArgumentException("No injectable id with value '"+key+"' found (for property '"+forProperty.getName()+"')");
}
return ob;
}
}
}
jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind/JavaType.java 0000664 0000000 0000000 00000043425 13604243101 0033167 0 ustar 00root root 0000000 0000000 package com.fasterxml.jackson.databind;
import java.lang.reflect.Modifier;
import java.util.List;
import com.fasterxml.jackson.core.type.ResolvedType;
import com.fasterxml.jackson.databind.type.TypeBindings;
import com.fasterxml.jackson.databind.type.TypeFactory;
/**
* Base class for type token classes used both to contain information
* and as keys for deserializers.
*
* 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
{
private static final long serialVersionUID = 1;
/**
* This is the nominal type-erased Class that would be close to the
* type represented (but not exactly type, due to type erasure: type
* instance may have more information on this).
* May be an interface or abstract class, so instantiation
* may not be possible.
*/
protected final Class> _class;
protected final int _hash;
/**
* Optional handler (codec) that can be attached to indicate
* what to use for handling (serializing, deserializing) values of
* this specific type.
*
* Note: untyped (i.e. caller has to cast) because it is used for
* different kinds of handlers, with unrelated types.
*/
protected final Object _valueHandler;
/**
* Optional handler that can be attached to indicate how to handle
* additional type metadata associated with this type.
*
* Note: untyped (i.e. caller has to cast) because it is used for
* different kinds of handlers, with unrelated types.
*/
protected final Object _typeHandler;
/**
* 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;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
/**
* @param raw "Raw" (type-erased) class for this type
* @param additionalHash Additional hash code to use, in addition
* to hash code of the class name
*/
protected JavaType(Class> raw, int additionalHash,
Object valueHandler, Object typeHandler, boolean asStatic)
{
_class = raw;
_hash = raw.getName().hashCode() + additionalHash;
_valueHandler = valueHandler;
_typeHandler = typeHandler;
_asStatic = asStatic;
}
/**
* Copy-constructor used when refining/upgrading type instances.
*
* @since 2.7
*/
protected JavaType(JavaType base)
{
_class = base._class;
_hash = base._hash;
_valueHandler = base._valueHandler;
_typeHandler = base._typeHandler;
_asStatic = base._asStatic;
}
/**
* "Copy method" that will construct a new instance that is identical to
* this instance, except that it will have specified type handler assigned.
*
* @return Newly created type instance
*/
public abstract JavaType withTypeHandler(Object h);
/**
* Mutant factory method that will construct a new instance that is identical to
* this instance, except that it will have specified content type (element type
* for arrays, value type for Maps and so forth) handler assigned.
*
* @return Newly created type instance, with given
*/
public abstract JavaType withContentTypeHandler(Object h);
/**
* Mutant factory method that will construct a new instance that is identical to
* this instance, except that it will have specified value handler assigned.
*
* @return Newly created type instance
*/
public abstract JavaType withValueHandler(Object h);
/**
* Mutant factory method that will construct a new instance that is identical to
* this instance, except that it will have specified content value handler assigned.
*
* @return Newly created type instance
*/
public abstract JavaType withContentValueHandler(Object h);
/**
* 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;
Object h = src.getTypeHandler();
if (h != _typeHandler) {
type = type.withTypeHandler(h);
}
h = src.getValueHandler();
if (h != _valueHandler) {
type = type.withValueHandler(h);
}
return type;
}
/**
* Mutant factory method that may be called on structured types
* that have a so-called content type (element of arrays, value type
* of Maps, referenced type of referential types),
* and will construct a new instance that is identical to
* this instance, except that it has specified content type, instead of current
* one. If content type is already set to given type, this
is returned.
* If type does not have a content type (which is the case with
* SimpleType
), {@link IllegalArgumentException}
* will be thrown.
*
* @return Newly created type instance
*
* @since 2.7
*/
public abstract JavaType withContentType(JavaType contentType);
/**
* Method that can be called to get a type instance that indicates
* that values of the type should be handled using "static typing" for purposes
* of serialization (as opposed to "dynamic" aka runtime typing):
* meaning that no runtime information is needed for determining serializers to use.
* 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();
/*
/**********************************************************
/* Type coercion fluent factory methods
/**********************************************************
*/
/**
* Mutant factory method that will try to create and return a sub-type instance
* 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);
/*
/**********************************************************
/* Implementation of ResolvedType API
/**********************************************************
*/
@Override
public final Class> getRawClass() { return _class; }
/**
* Method that can be used to check whether this type has
* specified Class as its type erasure. Put another way, returns
* true if instantiation of this Type is given (type-erased) Class.
*/
@Override
public final boolean hasRawClass(Class> clz) { return _class == clz; }
/**
* 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);
}
@Override
public boolean isAbstract() {
return Modifier.isAbstract(_class.getModifiers());
}
/**
* Convenience method for checking whether underlying Java type
* is a concrete class or not: abstract classes and interfaces
* are not.
*/
@Override
public boolean isConcrete() {
int mod = _class.getModifiers();
if ((mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0) {
return true;
}
/* 19-Feb-2010, tatus: Holy mackarel; primitive types
* have 'abstract' flag set...
*/
return _class.isPrimitive();
}
@Override
public boolean isThrowable() { return Throwable.class.isAssignableFrom(_class); }
@Override
public boolean isArrayType() { return false; }
@Override
public final boolean isEnumType() {
// 29-Sep-2019, tatu: `Class.isEnum()` not enough to detect custom subtypes,
// but for some reason this fix will break couple of unit tests:
// See [databind#2480]:
// return ClassUtil.isEnumType(_class);
return _class.isEnum();
}
@Override
public final boolean isInterface() { return _class.isInterface(); }
@Override
public final boolean isPrimitive() { return _class.isPrimitive(); }
@Override
public final boolean isFinal() { return Modifier.isFinal(_class.getModifiers()); }
/**
* @return True if type represented is a container type; this includes
* array, Map and Collection types.
*/
@Override
public abstract boolean isContainerType();
/**
* @return True if type is either true {@link java.util.Collection} type,
* or something similar (meaning it has at least one type parameter,
* which describes type of contents)
*/
@Override
public boolean isCollectionLikeType() { return false; }
/**
* @return True if type is either true {@link java.util.Map} type,
* or something similar (meaning it has at least two type parameter;
* first one describing key type, second value type)
*/
@Override
public boolean isMapLikeType() { return false; }
/**
* Convenience method, short-hand for
*
* 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; }
/**
* Accessor for checking whether handlers for dealing with values of
* 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; }
/*
/**********************************************************
/* Public API, type parameter access; pass-through
/**********************************************************
*/
@Override
public boolean hasGenericTypes() { return containedTypeCount() > 0; }
@Override
public JavaType getKeyType() { return null; }
@Override
public JavaType getContentType() { return null; }
@Override // since 2.6
public JavaType getReferencedType() { return null; }
@Override
public abstract int containedTypeCount();
@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;
}
/*
/**********************************************************
/* Extended API beyond ResolvedType
/**********************************************************
*/
// NOTE: not defined in Resolved type
/**
* Convenience method that is functionally same as:
*
* JavaType t = containedType(index);
* if (t == null) {
* t = TypeFactory.unknownType();
* }
*
* and typically used to eliminate need for null checks for common case
* 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();
/**
* Method that may be called to find representation of given type
* within type hierarchy of this type: either this type (if this
* 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);
/*
/**********************************************************
/* Semi-public API, accessing handlers
/**********************************************************
*/
/**
* Method for accessing value handler associated with this type, if any
*/
@SuppressWarnings("unchecked")
public T getValueHandler() { return (T) _valueHandler; }
/**
* Method for accessing type handler associated with this type, if any
*/
@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; }
/**
* Helper method that checks whether this type, or its (optional) key
* 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);
}
/*
/**********************************************************
/* Support for producing signatures
/**********************************************************
*/
//public abstract String toCanonical();
/**
* Method for accessing signature that contains generic
* type information, in form compatible with JVM 1.5
* as per JLS. It is a superset of {@link #getErasedSignature},
* in that generic information can be automatically removed
* if necessary (just remove outermost
* angle brackets along with content inside)
*/
public String getGenericSignature() {
StringBuilder sb = new StringBuilder(40);
getGenericSignature(sb);
return sb.toString();
}
/**
*
* @param sb StringBuilder to append signature to
*
* @return StringBuilder that was passed in; returned to allow
* call chaining
*/
public abstract StringBuilder getGenericSignature(StringBuilder sb);
/**
* Method for accessing signature without generic
* type information, in form compatible with all versions
* of JVM, and specifically used for type descriptions
* when generating byte code.
*/
public String getErasedSignature() {
StringBuilder sb = new StringBuilder(40);
getErasedSignature(sb);
return sb.toString();
}
/**
* Method for accessing signature without generic
* type information, in form compatible with all versions
* of JVM, and specifically used for type descriptions
* when generating byte code.
*
* @param sb StringBuilder to append signature to
*
* @return StringBuilder that was passed in; returned to allow
* call chaining
*/
public abstract StringBuilder getErasedSignature(StringBuilder sb);
/*
/**********************************************************
/* Standard methods; let's make them abstract to force override
/**********************************************************
*/
@Override
public abstract String toString();
@Override
public abstract boolean equals(Object o);
@Override
public final int hashCode() { return _hash; }
}
JsonDeserializer.java 0000664 0000000 0000000 00000043651 13604243101 0034642 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.IOException;
import java.util.Collection;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.util.AccessPattern;
import com.fasterxml.jackson.databind.util.NameTransformer;
/**
* Abstract class that defines API used by {@link ObjectMapper} (and
* other chained {@link JsonDeserializer}s too) to deserialize Objects of
* arbitrary types from JSON, using provided {@link JsonParser}.
*
* Custom deserializers should usually not directly extend this class,
* but instead extend {@link com.fasterxml.jackson.databind.deser.std.StdDeserializer}
* (or its subtypes like {@link com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer}).
*
* 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},
* 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
* to deserializer itself, directly or indirectly).
*
* 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
* 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.
*/
public abstract class JsonDeserializer
implements NullValueProvider // since 2.9
{
/*
/**********************************************************
/* Main deserialization methods
/**********************************************************
*/
/**
* Method that can be called to ask implementation to deserialize
* JSON content into the value type this serializer handles.
* Returned instance is to be constructed by method itself.
*
* Pre-condition for this method is that the parser points to the
* first event that is part of value to deserializer (and which
* is never JSON 'null' literal, more on this below): for simple
* types it may be the only value; and for structured types the
* Object start marker or a FIELD_NAME.
*
*
* The two possible input conditions for structured types result
* from polymorphism via fields. In the ordinary case, Jackson
* calls this method when it has encountered an OBJECT_START,
* and the method implementation must advance to the next token to
* see the first field name. If the application configures
* polymorphism via a field, then the object looks like the following.
*
* {
* "@class": "class name",
* ...
* }
*
* Jackson consumes the two tokens (the @class field name
* and its value) in order to learn the class and select the deserializer.
* Thus, the stream is pointing to the FIELD_NAME for the first field
* after the @class. Thus, if you want your method to work correctly
* both with and without polymorphism, you must begin your method with:
*
* if (p.currentToken() == JsonToken.START_OBJECT) {
* p.nextToken();
* }
*
* This results in the stream pointing to the field name, so that
* the two conditions align.
*
* Post-condition is that the parser will point to the last
* event that is part of deserialized value (or in case deserialization
* fails, event that was not recognized or usable, which may be
* the same event as the one it pointed to upon call).
*
* Note that this method is never called for JSON null literal,
* and thus deserializers need (and should) not check for it.
*
* @param p Parsed used for reading JSON content
* @param ctxt Context that can be used to access information about
* this deserialization activity.
*
* @return Deserialized value
*/
public abstract T deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException;
/**
* Alternate deserialization method (compared to the most commonly
* used, {@link #deserialize(JsonParser, DeserializationContext)}),
* which takes in initialized value instance, to be
* configured and/or populated by deserializer.
* Method is not necessarily used (or supported) by all types
* (it will not work for immutable types, for obvious reasons):
* most commonly it is used for Collections and Maps.
* It may be used both with "updating readers" (for POJOs) and
* when Collections and Maps use "getter as setter".
*
* Default implementation just throws
* {@link UnsupportedOperationException}, to indicate that types
* that do not explicitly add support do not necessarily support
* update-existing-value operation (esp. immutable types)
*/
public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue)
throws IOException
{
ctxt.handleBadMerge(this);
return deserialize(p, ctxt);
}
/**
* Deserialization called when type being deserialized is defined to
* contain additional type identifier, to allow for correctly
* instantiating correct subtype. This can be due to annotation on
* type (or its supertype), or due to global settings without
* annotations.
*
* Default implementation may work for some types, but ideally subclasses
* should not rely on current default implementation.
* Implementation is mostly provided to avoid compilation errors with older
* code.
*
* @param typeDeserializer Deserializer to use for handling type information
*/
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException
{
// We could try calling
return typeDeserializer.deserializeTypedFromAny(p, ctxt);
}
/**
* Method similar to {@link #deserializeWithType(JsonParser,DeserializationContext,TypeDeserializer)}
* but called when merging value. Considered "bad merge" by default implementation,
* but if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled will simple delegate to
* {@link #deserializeWithType(JsonParser, DeserializationContext, TypeDeserializer)}.
*
* @since 2.10
*/
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
TypeDeserializer typeDeserializer, T intoValue)
throws IOException
{
ctxt.handleBadMerge(this);
return deserializeWithType(p, ctxt, typeDeserializer);
}
/*
/**********************************************************
/* Fluent factory methods for constructing decorated versions
/**********************************************************
*/
/**
* Method that will return deserializer instance that is able
* to handle "unwrapped" value instances
* If no unwrapped instance can be constructed, will simply
* return this object as-is.
*
* Default implementation just returns 'this'
* indicating that no unwrapped variant exists
*/
public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) {
return this;
}
/**
* Method that can be called to try to replace deserializer this deserializer
* delegates calls to. If not supported (either this deserializer does not
* 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
/**********************************************************
*/
/**
* Method for accessing type of values this deserializer produces.
* Note that this information is not guaranteed to be exact -- it
* may be a more generic (super-type) -- but it should not be
* incorrect (return a non-related type).
*
* 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; }
/**
* Method called to see if deserializer instance is cachable and
* 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
* 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.
*/
public boolean isCachable() { return false; }
/**
* Accessor that can be used to determine if this deserializer uses
* another deserializer for actual deserialization, by delegating
* calls. If so, will return immediate delegate (which itself may
* delegate to further deserializers); otherwise will return null.
*
* @return Deserializer this deserializer delegates calls to, if null;
* null otherwise.
*
* @since 2.1
*/
public JsonDeserializer> getDelegatee() {
return null;
}
/**
* Method that will
* either return null to indicate that type being deserializers
* has no concept of properties; or a collection of identifiers
* for which toString
will give external property
* name.
* 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
/**********************************************************
*/
/**
* Method that can be called to determine value to be used for
* representing null values (values deserialized when JSON token
* is {@link JsonToken#VALUE_NULL}). Usually this is simply
* Java null, but for some types (especially primitives) it may be
* necessary to use non-null values.
*
* This method may be called once, or multiple times, depending on what
* {@link #getNullAccessPattern()} returns.
*
* 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();
}
/**
* This method may be called in conjunction with calls to
* {@link #getNullValue(DeserializationContext)}, to check whether it needs
* to be called just once (static values), or each time empty value is
* needed.
*
* Default implementation indicates that "null value" to use for input null
* is simply Java `null` for all deserializers, unless overridden by sub-classes.
* This information may be used as optimization.
*/
@Override
public AccessPattern getNullAccessPattern() {
// Default implementation assumes that the null value does not vary, which
// is usually the case for most implementations. But it is not necessarily
// `null`; so sub-classes may want to refine further.
return AccessPattern.CONSTANT;
}
/**
* This method may be called in conjunction with calls to
* {@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
/**********************************************************
*/
/**
* Method called to determine value to be used for "empty" values
* (most commonly when deserializing from empty JSON Strings).
* Usually this is same as {@link #getNullValue} (which in turn
* is usually simply Java null), but it can be overridden
* for specific types. Or, if type should never be converted from empty
* String, method can also throw an exception.
*
* This method may be called once, or multiple times, depending on what
* {@link #getEmptyAccessPattern()} returns.
*
* 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);
}
/**
* Accessor that can be used to check whether this deserializer
* is expecting to possibly get an Object Identifier value instead of full value
* serialization, and if so, should be able to resolve it to actual
* Object instance to return as deserialized value.
*
* Default implementation returns null, as support cannot be implemented
* generically. Some standard deserializers (most notably
* {@link com.fasterxml.jackson.databind.deser.BeanDeserializer})
* do implement this feature, and may return reader instance, depending on exact
* configuration of instance (which is based on type, and referring property).
*
* @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; }
/**
* 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)
{
throw new IllegalArgumentException("Cannot handle managed/back reference '"+refName
+"': type: value deserializer of type "+getClass().getName()+" does not support them");
}
/**
* Introspection method that may be called to see whether deserializer supports
* update of an existing value (aka "merging") or not. Return value should either
* be {@link Boolean#FALSE} if update is not supported at all (immutable values);
* {@link Boolean#TRUE} if update should usually work (regular POJOs, for example),
* or null
if this is either not known, or may sometimes work.
*
* Information gathered is typically used to either prevent merging update for
* property (either by skipping, if based on global defaults; or by exception during
* deserialization construction if explicit attempt made) if {@link Boolean#FALSE}
* returned, or inclusion if {@link Boolean#TRUE} is specified. If "unknown" case
* (null
returned) behavior is to exclude property if global defaults
* used; or to allow if explicit per-type or property merging is defined.
*
* 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
/**********************************************************
*/
/**
* This marker class is only to be used with annotations, to
* indicate that no deserializer is configured .
*
* Specifically, this class is to be used as the marker for
* annotation {@link com.fasterxml.jackson.databind.annotation.JsonDeserialize}
*/
public abstract static class None extends JsonDeserializer {
private None() { } // not to be instantiated
}
}
JsonMappingException.java 0000664 0000000 0000000 00000042462 13604243101 0035471 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.Closeable;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Checked exception used to signal fatal problems with mapping of
* content, distinct from low-level I/O problems (signaled using
* simple {@link java.io.IOException}s) or data encoding/decoding
* problems (signaled with {@link com.fasterxml.jackson.core.JsonParseException},
* {@link com.fasterxml.jackson.core.JsonGenerationException}).
*
* One additional feature is the ability to denote relevant path
* of references (during serialization/deserialization) to help in
* troubleshooting.
*/
public class JsonMappingException
extends JsonProcessingException
{
private static final long serialVersionUID = 1L;
/**
* Let's limit length of reference chain, to limit damage in cases
* of infinite recursion.
*/
final static int MAX_REFS_TO_LIST = 1000;
/*
/**********************************************************
/* Helper classes
/**********************************************************
*/
/**
* Simple bean class used to contain references. References
* can be added to indicate execution/reference path that
* lead to the problem that caused this exception to be
* thrown.
*/
public static class Reference implements Serializable
{
private static final long serialVersionUID = 2L; // changes between 2.7 and 2.8
// transient since 2.8
protected transient Object _from;
/**
* Name of field (for beans) or key (for Maps) that is part
* of the reference. May be null for Collection types (which
* generally have {@link #_index} defined), or when resolving
* Map classes without (yet) having an instance to operate on.
*/
protected String _fieldName;
/**
* Index within a {@link Collection} instance that contained
* the reference; used if index is relevant and available.
* If either not applicable, or not available, -1 is used to
* denote "not known" (or not relevant).
*/
protected int _index = -1;
/**
* Lazily-constructed description of this instance; needed mostly to
* allow JDK serialization to work in case where {@link #_from} is
* non-serializable (and has to be dropped) but we still want to pass
* actual description along.
*
* @since 2.8
*/
protected String _desc;
/**
* Default constructor for deserialization/sub-classing purposes
*/
protected Reference() { }
public Reference(Object from) { _from = from; }
public Reference(Object from, String fieldName) {
_from = from;
if (fieldName == null) {
throw new NullPointerException("Cannot pass null fieldName");
}
_fieldName = fieldName;
}
public Reference(Object from, int index) {
_from = from;
_index = index;
}
// Setters to let Jackson deserialize instances, but not to be called from outside
void setFieldName(String n) { _fieldName = n; }
void setIndex(int ix) { _index = ix; }
void setDescription(String d) { _desc = d; }
/**
* Object through which reference was resolved. Can be either
* actual instance (usually the case for serialization), or
* Class (usually the case for deserialization).
*
* Note that this value must be `transient` to allow serializability (as
* often such Object is NOT serializable; or, in case of `Class`, may
* not available at the point of deserialization). As such will return
* `null` if instance has been passed using JDK serialization.
*/
@JsonIgnore
public Object getFrom() { return _from; }
public String getFieldName() { return _fieldName; }
public int getIndex() { return _index; }
public String getDescription() {
if (_desc == null) {
StringBuilder sb = new StringBuilder();
if (_from == null) { // can this ever occur?
sb.append("UNKNOWN");
} else {
Class> cls = (_from instanceof Class>) ? (Class>)_from : _from.getClass();
// Hmmh. Although Class.getName() is mostly ok, it does look
// butt-ugly for arrays.
// 06-Oct-2016, tatu: as per [databind#1403], `getSimpleName()` not so good
// as it drops enclosing class. So let's try bit different approach
int arrays = 0;
while (cls.isArray()) {
cls = cls.getComponentType();
++arrays;
}
sb.append(cls.getName());
while (--arrays >= 0) {
sb.append("[]");
}
/* was:
String pkgName = ClassUtil.getPackageName(cls);
if (pkgName != null) {
sb.append(pkgName);
sb.append('.');
}
*/
}
sb.append('[');
if (_fieldName != null) {
sb.append('"');
sb.append(_fieldName);
sb.append('"');
} else if (_index >= 0) {
sb.append(_index);
} else {
sb.append('?');
}
sb.append(']');
_desc = sb.toString();
}
return _desc;
}
@Override
public String toString() {
return getDescription();
}
/**
* May need some cleaning here, given that `from` may or may not be serializable.
*
* since 2.8
*/
Object writeReplace() {
// as per [databind#1195], need to ensure description is not null, since
// `_from` is transient
getDescription();
return this;
}
}
/*
/**********************************************************
/* State/configuration
/**********************************************************
*/
/**
* Path through which problem that triggering throwing of
* this exception was reached.
*/
protected LinkedList _path;
/**
* Underlying processor ({@link JsonParser} or {@link JsonGenerator}),
* if known.
*
* NOTE: typically not serializable hence transient
*
* @since 2.7
*/
protected transient Closeable _processor;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
/**
* @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;
if (processor instanceof JsonParser) {
// 17-Aug-2015, tatu: Use of token location makes some sense from databinding,
// since actual parsing (current) location is typically only needed for low-level
// parsing exceptions.
_location = ((JsonParser) processor).getTokenLocation();
}
}
/**
* @since 2.7
*/
public JsonMappingException(Closeable processor, String msg, Throwable problem) {
super(msg, problem);
_processor = processor;
if (processor instanceof JsonParser) {
_location = ((JsonParser) processor).getTokenLocation();
}
}
/**
* @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
* a signature.
*
* 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,
String.format("Unexpected IOException (of type %s): %s",
src.getClass().getName(),
ClassUtil.exceptionMessage(src)));
}
/**
* Method that can be called to either create a new JsonMappingException
* (if underlying exception is not a JsonMappingException), or augment
* given exception with given path/reference information.
*
* This version of method is called when the reference is through a
* non-indexed object, such as a Map or POJO/bean.
*/
public static JsonMappingException wrapWithPath(Throwable src, Object refFrom,
String refFieldName) {
return wrapWithPath(src, new Reference(refFrom, refFieldName));
}
/**
* Method that can be called to either create a new JsonMappingException
* (if underlying exception is not a JsonMappingException), or augment
* given exception with given path/reference information.
*
* This version of method is called when the reference is through an
* index, which happens with arrays and Collections.
*/
public static JsonMappingException wrapWithPath(Throwable src, Object refFrom, int index) {
return wrapWithPath(src, new Reference(refFrom, index));
}
/**
* Method that can be called to either create a new JsonMappingException
* (if underlying exception is not a JsonMappingException), or augment
* given exception with given path/reference information.
*/
@SuppressWarnings("resource")
public static JsonMappingException wrapWithPath(Throwable src, Reference ref)
{
JsonMappingException jme;
if (src instanceof JsonMappingException) {
jme = (JsonMappingException) src;
} else {
// [databind#2128]: try to avoid duplication
String msg = ClassUtil.exceptionMessage(src);
// Let's use a more meaningful placeholder if all we have is null
if (msg == null || msg.length() == 0) {
msg = "(was "+src.getClass().getName()+")";
}
// 17-Aug-2015, tatu: Let's also pass the processor (parser/generator) along
Closeable proc = null;
if (src instanceof JsonProcessingException) {
Object proc0 = ((JsonProcessingException) src).getProcessor();
if (proc0 instanceof Closeable) {
proc = (Closeable) proc0;
}
}
jme = new JsonMappingException(proc, msg, src);
}
jme.prependPath(ref);
return jme;
}
/*
/**********************************************************
/* Accessors/mutators
/**********************************************************
*/
/**
* Method for accessing full structural path within type hierarchy
* down to problematic property.
*/
public List getPath()
{
if (_path == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(_path);
}
/**
* Method for accessing description of path that lead to the
* problem that triggered this exception
*/
public String getPathReference()
{
return getPathReference(new StringBuilder()).toString();
}
public StringBuilder getPathReference(StringBuilder sb)
{
_appendPathDesc(sb);
return sb;
}
/**
* Method called to prepend a reference information in front of
* current path
*/
public void prependPath(Object referrer, String fieldName)
{
Reference ref = new Reference(referrer, fieldName);
prependPath(ref);
}
/**
* Method called to prepend a reference information in front of
* current path
*/
public void prependPath(Object referrer, int index)
{
Reference ref = new Reference(referrer, index);
prependPath(ref);
}
public void prependPath(Reference r)
{
if (_path == null) {
_path = new LinkedList();
}
/* Also: let's not increase without bounds. Could choose either
* head or tail; tail is easier (no need to ever remove), as
* well as potentially more useful so let's use it:
*/
if (_path.size() < MAX_REFS_TO_LIST) {
_path.addFirst(r);
}
}
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override // since 2.7.5
@JsonIgnore // as per [databind#1368]
public Object getProcessor() { return _processor; }
@Override
public String getLocalizedMessage() {
return _buildMessage();
}
/**
* Method is overridden so that we can properly inject description
* of problem path, if such is defined.
*/
@Override
public String getMessage() {
return _buildMessage();
}
protected String _buildMessage()
{
// First: if we have no path info, let's just use parent's definition as is
String msg = super.getMessage();
if (_path == null) {
return msg;
}
StringBuilder sb = (msg == null) ? new StringBuilder() : new StringBuilder(msg);
/* 18-Feb-2009, tatu: initially there was a linefeed between
* message and path reference; but unfortunately many systems
* (loggers, junit) seem to assume linefeeds are only added to
* separate stack trace.
*/
sb.append(" (through reference chain: ");
sb = getPathReference(sb);
sb.append(')');
return sb.toString();
}
@Override
public String toString()
{
return getClass().getName()+": "+getMessage();
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected void _appendPathDesc(StringBuilder sb)
{
if (_path == null) {
return;
}
Iterator it = _path.iterator();
while (it.hasNext()) {
sb.append(it.next().toString());
if (it.hasNext()) {
sb.append("->");
}
}
}
}
jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind/JsonNode.java 0000664 0000000 0000000 00000122737 13604243101 0033167 0 ustar 00root root 0000000 0000000 package com.fasterxml.jackson.databind;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Base class for all JSON nodes, which form the basis of JSON
* Tree Model that Jackson implements.
* One way to think of these nodes is to consider them
* similar to DOM nodes in XML DOM trees.
*
* As a general design rule, most accessors ("getters") are included
* in this base class, to allow for traversing structure without
* type casts. Most mutators, however, need to be accessed through
* specific sub-classes (such as ObjectNode
* and ArrayNode
).
* This seems sensible because proper type
* information is generally available when building or modifying
* trees, but less often when reading a tree (newly built from
* parsed JSON content).
*
* Actual concrete sub-classes can be found from package
* {@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
* 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)}
* and {@link ObjectMapper#treeAsTokens(TreeNode)}
*/
public abstract class JsonNode
extends JsonSerializable.Base // i.e. implements JsonSerializable
implements TreeNode, Iterable
{
/*
/**********************************************************
/* Construction, related
/**********************************************************
*/
protected JsonNode() { }
/**
* Method that can be called to get a node that is guaranteed
* not to allow changing of this node through mutators on
* this node or any of its children.
* This means it can either make a copy of this node (and all
* mutable children and grand children nodes), or node itself
* if it is immutable.
*
* 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();
// public abstract JsonToken traverse();
// public abstract JsonToken traverse(ObjectCodec codec);
// public abstract JsonParser.NumberType numberType();
@Override
public int size() { return 0; }
/**
* Convenience method that is functionally same as:
*
* size() == 0
*
* for all node types.
*
* @since 2.10
*/
public boolean isEmpty() { return size() == 0; }
@Override
public final boolean isValueNode()
{
switch (getNodeType()) {
case ARRAY: case OBJECT: case MISSING:
return false;
default:
return true;
}
}
@Override
public final boolean isContainerNode() {
final JsonNodeType type = getNodeType();
return type == JsonNodeType.OBJECT || type == JsonNodeType.ARRAY;
}
@Override
public boolean isMissingNode() {
return false;
}
@Override
public boolean isArray() {
return false;
}
@Override
public boolean isObject() {
return false;
}
/**
* Method for accessing value of the specified element of
* an array node. For other nodes, null is always returned.
*
* For array nodes, index specifies
* exact location within array and allows for efficient iteration
* over child elements (underlying storage is guaranteed to
* be efficiently indexable, i.e. has random-access to elements).
* If index is less than 0, or equal-or-greater than
* node.size()
, null is returned; no exception is
* thrown for any index.
*
* NOTE: if the element value has been explicitly set as null
* (which is different from removal!),
* a {@link com.fasterxml.jackson.databind.node.NullNode} will be returned,
* not null.
*
* @return Node that represent value of the specified element,
* if this node is an array and has specified element.
* Null otherwise.
*/
@Override
public abstract JsonNode get(int index);
/**
* Method for accessing value of the specified field of
* an object node. If this node is not an object (or it
* does not have a value for specified field name), or
* if there is no field with such name, null is returned.
*
* NOTE: if the property value has been explicitly set as null
* (which is different from removal!),
* a {@link com.fasterxml.jackson.databind.node.NullNode} will be returned,
* not null.
*
* @return Node that represent value of the specified field,
* if this node is an object and has value for the specified
* field. Null otherwise.
*/
@Override
public JsonNode get(String fieldName) { return null; }
/**
* This method is similar to {@link #get(String)}, except
* that instead of returning null if no such value exists (due
* to this node not being an object, or object not having value
* for the specified field),
* a "missing node" (node that returns true for
* {@link #isMissingNode}) will be returned. This allows for
* convenient and safe chained access via path calls.
*/
@Override
public abstract JsonNode path(String fieldName);
/**
* This method is similar to {@link #get(int)}, except
* that instead of returning null if no such element exists (due
* to index being out of range, or this node not being an array),
* a "missing node" (node that returns true for
* {@link #isMissingNode}) will be returned. This allows for
* convenient and safe chained access via path calls.
*/
@Override
public abstract JsonNode path(int index);
@Override
public Iterator fieldNames() {
return ClassUtil.emptyIterator();
}
/**
* Method for locating node specified by given JSON pointer instances.
* Method will never return null; if no matching node exists,
* will return a node for which {@link #isMissingNode()} returns true.
*
* @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)
{
// Basically: value nodes only match if we have "empty" path left
if (ptr.matches()) {
return this;
}
JsonNode n = _at(ptr);
if (n == null) {
return MissingNode.getInstance();
}
return n.at(ptr.tail());
}
/**
* Convenience method that is functionally equivalent to:
*
* return at(JsonPointer.valueOf(jsonPointerExpression));
*
*
* Note that if the same expression is used often, it is preferable to construct
* {@link JsonPointer} instance once and reuse it: this method will not perform
* any caching of compiled expressions.
*
* @param jsonPtrExpr Expression to compile as a {@link JsonPointer}
* instance
*
* @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) {
return at(JsonPointer.compile(jsonPtrExpr));
}
protected abstract JsonNode _at(JsonPointer ptr);
/*
/**********************************************************
/* Public API, type introspection
/**********************************************************
*/
// // First high-level division between values, containers and "missing"
/**
* Return the type of this node
*
* @return the node type as a {@link JsonNodeType} enum value
*
* @since 2.2
*/
public abstract JsonNodeType getNodeType();
/**
* Method that can be used to check if the node is a wrapper
* for a POJO ("Plain Old Java Object" aka "bean".
* Returns true only for
* instances of POJONode
.
*
* @return True if this node wraps a POJO
*/
public final boolean isPojo() {
return getNodeType() == JsonNodeType.POJO;
}
/**
* @return True if this node represents a numeric JSON value
*/
public final boolean isNumber() {
return getNodeType() == JsonNodeType.NUMBER;
}
/**
*
* @return True if this node represents an integral (integer)
* numeric JSON value
*/
public boolean isIntegralNumber() { return false; }
/**
* @return True if this node represents a non-integral
* numeric JSON value
*/
public boolean isFloatingPointNumber() { return false; }
/**
* Method that can be used to check whether contained value
* is a number represented as Java short
.
* Note, however, that even if this method returns false, it
* is possible that conversion would be possible from other numeric
* types -- to check if this is possible, use
* {@link #canConvertToInt()} instead.
*
* @return True if the value contained by this node is stored as Java short
*/
public boolean isShort() { return false; }
/**
* Method that can be used to check whether contained value
* is a number represented as Java int
.
* Note, however, that even if this method returns false, it
* is possible that conversion would be possible from other numeric
* types -- to check if this is possible, use
* {@link #canConvertToInt()} instead.
*
* @return True if the value contained by this node is stored as Java int
*/
public boolean isInt() { return false; }
/**
* Method that can be used to check whether contained value
* is a number represented as Java long
.
* Note, however, that even if this method returns false, it
* is possible that conversion would be possible from other numeric
* types -- to check if this is possible, use
* {@link #canConvertToLong()} instead.
*
* @return True if the value contained by this node is stored as Java long
*/
public boolean isLong() { return false; }
/**
* @since 2.2
*/
public boolean isFloat() { return false; }
public boolean isDouble() { return false; }
public boolean isBigDecimal() { return false; }
public boolean isBigInteger() { return false; }
/**
* Method that checks whether this node represents basic JSON String
* value.
*/
public final boolean isTextual() {
return getNodeType() == JsonNodeType.STRING;
}
/**
* Method that can be used to check if this node was created from
* JSON boolean value (literals "true" and "false").
*/
public final boolean isBoolean() {
return getNodeType() == JsonNodeType.BOOLEAN;
}
/**
* Method that can be used to check if this node was created from
* JSON literal null value.
*/
public final boolean isNull() {
return getNodeType() == JsonNodeType.NULL;
}
/**
* Method that can be used to check if this node represents
* binary data (Base64 encoded). Although this will be externally
* written as JSON String value, {@link #isTextual} will
* return false if this method returns true.
*
* @return True if this node represents base64 encoded binary data
*/
public final boolean isBinary() {
return getNodeType() == JsonNodeType.BINARY;
}
/**
* Method that can be used to check whether this node is a numeric
* node ({@link #isNumber} would return true) AND its value fits
* within Java's 32-bit signed integer type, int
.
* Note that floating-point numbers are convertible if the integral
* part fits without overflow (as per standard Java coercion rules)
*
* NOTE: this method does not consider possible value type conversion
* 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; }
/**
* Method that can be used to check whether this node is a numeric
* node ({@link #isNumber} would return true) AND its value fits
* within Java's 64-bit signed integer type, long
.
* Note that floating-point numbers are convertible if the integral
* part fits without overflow (as per standard Java coercion rules)
*
* NOTE: this method does not consider possible value type conversion
* 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
/**********************************************************
*/
/**
* Method to use for accessing String values.
* Does NOT do any conversions for non-String value nodes;
* for non-String values (ones for which {@link #isTextual} returns
* false) null will be returned.
* For String values, null is never returned (but empty Strings may be)
*
* @return Textual value this node contains, iff it is a textual
* JSON node (comes from JSON String value entry)
*/
public String textValue() { return null; }
/**
* Method to use for accessing binary content of binary nodes (nodes
* for which {@link #isBinary} returns true); or for Text Nodes
* (ones for which {@link #textValue} returns non-null value),
* to read decoded base64 data.
* For other types of nodes, returns null.
*
* @return Binary data this node contains, iff it is a binary
* node; null otherwise
*/
public byte[] binaryValue() throws IOException {
return null;
}
/**
* Method to use for accessing JSON boolean values (value
* literals 'true' and 'false').
* For other types, always returns false.
*
* @return Textual value this node contains, iff it is a textual
* json node (comes from JSON String value entry)
*/
public boolean booleanValue() { return false; }
/**
* Returns numeric value for this node, if and only if
* this node is numeric ({@link #isNumber} returns true); otherwise
* returns null
*
* @return Number value this node contains, if any (null for non-number
* nodes).
*/
public Number numberValue() { return null; }
/**
* Returns 16-bit short value for this node, if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns 0.
* For floating-point numbers, value is truncated using default
* Java coercion, similar to how cast from double to short operates.
*
* @return Short value this node contains, if any; 0 for non-number
* nodes.
*/
public short shortValue() { return 0; }
/**
* Returns integer value for this node, if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns 0.
* For floating-point numbers, value is truncated using default
* Java coercion, similar to how cast from double to int operates.
*
* @return Integer value this node contains, if any; 0 for non-number
* nodes.
*/
public int intValue() { return 0; }
/**
* Returns 64-bit long value for this node, if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns 0.
* For floating-point numbers, value is truncated using default
* Java coercion, similar to how cast from double to long operates.
*
* @return Long value this node contains, if any; 0 for non-number
* nodes.
*/
public long longValue() { return 0L; }
/**
* Returns 32-bit floating value for this node, if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns 0.0.
* For integer values, conversion is done using coercion; this means
* 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; }
/**
* Returns 64-bit floating point (double) value for this node, if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns 0.0.
* For integer values, conversion is done using coercion; this may result
* 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; }
/**
* Returns floating point value for this node (as {@link BigDecimal}), if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns BigDecimal.ZERO
.
*
* @return {@link BigDecimal} value this node contains, if numeric node; BigDecimal.ZERO
for non-number nodes.
*/
public BigDecimal decimalValue() { return BigDecimal.ZERO; }
/**
* Returns integer value for this node (as {@link BigDecimal}), if and only if
* this node is numeric ({@link #isNumber} returns true). For other
* types returns BigInteger.ZERO
.
*
* @return {@link BigInteger} value this node contains, if numeric node; BigInteger.ZERO
for non-number nodes.
*/
public BigInteger bigIntegerValue() { return BigInteger.ZERO; }
/*
/**********************************************************
/* Public API, value access with conversion(s)/coercion(s)
/**********************************************************
*/
/**
* Method that will return a valid String representation of
* the container value, if the node is a value node
* (method {@link #isValueNode} returns true),
* otherwise empty String.
*/
public abstract String asText();
/**
* Method similar to {@link #asText()}, except that it will return
* 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();
return (str == null) ? defaultValue : str;
}
/**
* 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.
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
* default value of 0 will be returned; no exceptions are thrown.
*/
public int asInt() {
return asInt(0);
}
/**
* 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.
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
* specified defaultValue will be returned; no exceptions are thrown.
*/
public int asInt(int defaultValue) {
return 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.
*
* If representation cannot be converted to an long (including structured types
* like Objects and Arrays),
* default value of 0 will be returned; no exceptions are thrown.
*/
public long asLong() {
return asLong(0L);
}
/**
* 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.
*
* If representation cannot be converted to an long (including structured types
* like Objects and Arrays),
* specified defaultValue will be returned; no exceptions are thrown.
*/
public long asLong(long defaultValue) {
return 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.
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
* default value of 0.0 will be returned; no exceptions are thrown.
*/
public double asDouble() {
return asDouble(0.0);
}
/**
* 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.
*
* If representation cannot be converted to an int (including structured types
* like Objects and Arrays),
* specified defaultValue will be returned; no exceptions are thrown.
*/
public double asDouble(double defaultValue) {
return defaultValue;
}
/**
* Method that will try to convert value of this node to a Java boolean .
* JSON booleans map naturally; integer numbers other than 0 map to true, and
* 0 maps to false
* and Strings 'true' and 'false' map to corresponding values.
*
* If representation cannot be converted to a boolean value (including structured types
* like Objects and Arrays),
* default value of false will be returned; no exceptions are thrown.
*/
public boolean asBoolean() {
return asBoolean(false);
}
/**
* Method that will try to convert value of this node to a Java boolean .
* JSON booleans map naturally; integer numbers other than 0 map to true, and
* 0 maps to false
* and Strings 'true' and 'false' map to corresponding values.
*
* If representation cannot be converted to a boolean value (including structured types
* like Objects and Arrays),
* specified defaultValue will be returned; no exceptions are thrown.
*/
public boolean asBoolean(boolean defaultValue) {
return defaultValue;
}
/*
/**********************************************************************
/* Public API, extended traversal (2.10) with "required()"
/**********************************************************************
*/
/**
* Method that may be called to verify that {@code this} node is NOT so-called
* "missing node": that is, one for which {@link #isMissingNode()} returns {@code true}.
* If not missing node, {@code this} is returned to allow chaining; otherwise
* {@link IllegalArgumentException} is thrown.
*
* @return {@code this} node to allow chaining
*
* @throws IllegalArgumentException if this node is "missing node"
*
* @since 2.10
*/
public T require() throws IllegalArgumentException {
return _this();
}
/**
* Method that may be called to verify that {@code this} node is neither so-called
* "missing node" (that is, one for which {@link #isMissingNode()} returns {@code true})
* nor "null node" (one for which {@link #isNull()} returns {@code true}).
* If non-null non-missing node, {@code this} is returned to allow chaining; otherwise
* {@link IllegalArgumentException} is thrown.
*
* @return {@code this} node to allow chaining
*
* @throws IllegalArgumentException if this node is either "missing node" or "null node"
*
* @since 2.10
*/
public T requireNonNull() throws IllegalArgumentException {
return _this();
}
/**
* Method is functionally equivalent to
*{@code
* path(fieldName).required()
*}
* and can be used to check that this node is an {@code ObjectNode} (that is, represents
* JSON Object value) and has value for specified property with key {@code fieldName}
* (but note that value may be explicit JSON null value).
* If this node is Object Node and has value for specified property, {@code this} is returned
* to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
*
* @return {@code this} node to allow chaining
*
* @throws IllegalArgumentException if this node is not an Object node or if it does not
* have value for specified property
*
* @since 2.10
*/
public JsonNode required(String fieldName) throws IllegalArgumentException {
return _reportRequiredViolation("Node of type `%s` has no fields", getClass().getName());
}
/**
* Method is functionally equivalent to
*{@code
* path(index).required()
*}
* and can be used to check that this node is an {@code ArrayNode} (that is, represents
* JSON Array value) and has value for specified {@code index}
* (but note that value may be explicit JSON null value).
* If this node is Array Node and has value for specified index, {@code this} is returned
* to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
*
* @return {@code this} node to allow chaining
*
* @throws IllegalArgumentException if this node is not an Array node or if it does not
* have value for specified index
*
* @since 2.10
*/
public JsonNode required(int index) throws IllegalArgumentException {
return _reportRequiredViolation("Node of type `%s` has no indexed values", getClass().getName());
}
/**
* Method is functionally equivalent to
*{@code
* at(pathExpr).required()
*}
* and can be used to check that there is an actual value node at specified {@link JsonPointer}
* starting from {@code this} node
* (but note that value may be explicit JSON null value).
* If such value node exists {@code this} is returned
* to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
*
* @return {@code this} node to allow chaining
*
* @throws IllegalArgumentException if no value node exists at given {@code JSON Pointer} path
*
* @since 2.10
*/
public JsonNode requiredAt(String pathExpr) throws IllegalArgumentException {
return requiredAt(JsonPointer.compile(pathExpr));
}
/**
* Method is functionally equivalent to
*{@code
* at(path).required()
*}
* and can be used to check that there is an actual value node at specified {@link JsonPointer}
* starting from {@code this} node
* (but note that value may be explicit JSON null value).
* If such value node exists {@code this} is returned
* to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
*
* @return {@code this} node to allow chaining
*
* @throws IllegalArgumentException if no value node exists at given {@code JSON Pointer} path
*
* @since 2.10
*/
public final JsonNode requiredAt(final JsonPointer path) throws IllegalArgumentException {
JsonPointer currentExpr = path;
JsonNode curr = this;
// Note: copied from `at()`
while (true) {
if (currentExpr.matches()) {
return curr;
}
curr = curr._at(currentExpr);
if (curr == null) {
_reportRequiredViolation("No node at '%s' (unmatched part: '%s')",
path, currentExpr);
}
currentExpr = currentExpr.tail();
}
}
/*
/**********************************************************
/* Public API, value find / existence check methods
/**********************************************************
*/
/**
* Method that allows checking whether this node is JSON Object node
* and contains value for specified property. If this is the case
* (including properties with explicit null values), returns true;
* otherwise returns false.
*
* This method is equivalent to:
*
* node.get(fieldName) != null
*
* (since return value of get() is node, not value node contains)
*
* NOTE: when explicit null
values are added, this
* method will return true
for such properties.
*
* @param fieldName Name of element to check
*
* @return True if this node is a JSON Object node, and has a property
* entry with specified name (with any value, including null value)
*/
public boolean has(String fieldName) {
return get(fieldName) != null;
}
/**
* Method that allows checking whether this node is JSON Array node
* and contains a value for specified index
* If this is the case
* (including case of specified indexing having null as value), returns true;
* otherwise returns false.
*
* Note: array element indexes are 0-based.
*
* This method is equivalent to:
*
* node.get(index) != null
*
*
* NOTE: this method will return true
for explicitly added
* null values.
*
* @param index Index to check
*
* @return True if this node is a JSON Object node, and has a property
* entry with specified name (with any value, including null value)
*/
public boolean has(int index) {
return get(index) != null;
}
/**
* Method that is similar to {@link #has(String)}, but that will
* return false
for explicitly added nulls.
*
* This method is functionally equivalent to:
*
* node.get(fieldName) != null && !node.get(fieldName).isNull()
*
*
* @since 2.1
*/
public boolean hasNonNull(String fieldName) {
JsonNode n = get(fieldName);
return (n != null) && !n.isNull();
}
/**
* Method that is similar to {@link #has(int)}, but that will
* return false
for explicitly added nulls.
*
* This method is equivalent to:
*
* node.get(index) != null && !node.get(index).isNull()
*
*
* @since 2.1
*/
public boolean hasNonNull(int index) {
JsonNode n = get(index);
return (n != null) && !n.isNull();
}
/*
/**********************************************************
/* Public API, container access
/**********************************************************
*/
/**
* Same as calling {@link #elements}; implemented so that
* convenience "for-each" loop can be used for looping over elements
* of JSON Array constructs.
*/
@Override
public final Iterator iterator() { return elements(); }
/**
* Method for accessing all value nodes of this Node, iff
* this node is a JSON Array or Object node. In case of Object node,
* field names (keys) are not included, only values.
* For other types of nodes, returns empty iterator.
*/
public Iterator elements() {
return ClassUtil.emptyIterator();
}
/**
* @return Iterator that can be used to traverse all key/value pairs for
* object nodes; empty iterator (no contents) for other types
*/
public Iterator> fields() {
return ClassUtil.emptyIterator();
}
/*
/**********************************************************
/* Public API, find methods
/**********************************************************
*/
/**
* Method for finding a JSON Object field with specified name in this
* node or its child nodes, and returning value it has.
* If no matching field is found in this node or its descendants, returns null.
*
* @param fieldName Name of field to look for
*
* @return Value of first matching node found, if any; null if none
*/
public abstract JsonNode findValue(String fieldName);
/**
* Method for finding JSON Object fields with specified name, and returning
* found ones as a List. Note that sub-tree search ends if a field is found,
* so possible children of result nodes are not included.
* If no matching fields are found in this node or its descendants, returns
* an empty List.
*
* @param fieldName Name of field to look for
*/
public final List findValues(String fieldName)
{
List result = findValues(fieldName, null);
if (result == null) {
return Collections.emptyList();
}
return result;
}
/**
* Similar to {@link #findValues}, but will additionally convert
* values into Strings, calling {@link #asText}.
*/
public final List findValuesAsText(String fieldName)
{
List result = findValuesAsText(fieldName, null);
if (result == null) {
return Collections.emptyList();
}
return result;
}
/**
* Method similar to {@link #findValue}, but that will return a
* "missing node" instead of null if no field is found. Missing node
* is a specific kind of node for which {@link #isMissingNode}
* returns true; and all value access methods return empty or
* missing value.
*
* @param fieldName Name of field to look for
*
* @return Value of first matching node found; or if not found, a
* "missing node" (non-null instance that has no value)
*/
public abstract JsonNode findPath(String fieldName);
/**
* Method for finding a JSON Object that contains specified field,
* within this node or its descendants.
* If no matching field is found in this node or its descendants, returns null.
*
* @param fieldName Name of field to look for
*
* @return Value of first matching node found, if any; null if none
*/
public abstract JsonNode findParent(String fieldName);
/**
* Method for finding a JSON Object that contains specified field,
* within this node or its descendants.
* If no matching field is found in this node or its descendants, returns null.
*
* @param fieldName Name of field to look for
*
* @return Value of first matching node found, if any; null if none
*/
public final List findParents(String fieldName)
{
List result = findParents(fieldName, null);
if (result == null) {
return Collections.emptyList();
}
return result;
}
public abstract List findValues(String fieldName, List foundSoFar);
public abstract List findValuesAsText(String fieldName, List foundSoFar);
public abstract List findParents(String fieldName, List foundSoFar);
/*
/**********************************************************
/* Public API, path handling
/**********************************************************
*/
/**
* Method that can be called on Object nodes, to access a property
* that has Object value; or if no such property exists, to create,
* add and return such Object node.
* If the node method is called on is not Object node,
* or if property exists and has value that is not Object node,
* {@link UnsupportedOperationException} is thrown
*
* NOTE: since 2.10 has had co-variant return type
*/
public T with(String propertyName) {
throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but "
+getClass().getName()+"), cannot call with() on it");
}
/**
* Method that can be called on Object nodes, to access a property
* that has Array
value; or if no such property exists, to create,
* add and return such Array node.
* If the node method is called on is not Object node,
* or if property exists and has value that is not Array node,
* {@link UnsupportedOperationException} is thrown
*
* NOTE: since 2.10 has had co-variant return type
*/
public T withArray(String propertyName) {
throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but "
+getClass().getName()+"), cannot call withArray() on it");
}
/*
/**********************************************************
/* Public API, comparison
/**********************************************************
*/
/**
* Entry method for invoking customizable comparison, using passed-in
* {@link Comparator} object. Nodes will handle traversal of structured
* types (arrays, objects), but defer to comparator for scalar value
* comparisons. If a "natural" {@link Comparator} is passed -- one that
* simply calls equals()
on one of arguments, passing the other
* -- implementation is the same as directly calling equals()
* on node.
*
* Default implementation simply delegates to passed in comparator
,
* with this
as the first argument, and other
as
* the second argument.
*
* @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
* 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
* {@link ObjectMapper} or {@link ObjectWriter} to serialize an
* instance, for example:
*
* String json = objectMapper.writeValueAsString(rootNode);
*
*
* Note: method defined as abstract to ensure all implementation
* classes explicitly implement method, instead of relying
* on {@link Object#toString()} definition.
*/
@Override
public abstract String toString();
/**
* Alternative to {@link #toString} that will serialize this node using
* Jackson default pretty-printer.
*
* @since 2.10
*/
public String toPrettyString() {
return toString();
}
/**
* Equality for node objects is defined as full (deep) value
* equality. This means that it is possible to compare complete
* JSON trees for equality by comparing equality of root nodes.
*
* Note: marked as abstract to ensure all implementation
* classes define it properly and not rely on definition
* from {@link java.lang.Object}.
*/
@Override
public abstract boolean equals(Object o);
/*
/**********************************************************************
/* Helper methods, for sub-classes
/**********************************************************************
*/
// @since 2.10
@SuppressWarnings("unchecked")
protected T _this() {
return (T) this;
}
/**
* Helper method that throws {@link IllegalArgumentException} as a result of
* violating "required-constraint" for this node (for {@link #required} or related
* methods).
*/
protected T _reportRequiredViolation(String msgTemplate, Object...args) {
throw new IllegalArgumentException(String.format(msgTemplate, args));
}
}
JsonSerializable.java 0000664 0000000 0000000 00000004711 13604243101 0034620 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
/**
* Interface that can be implemented by objects that know how to
* serialize themselves to JSON, using {@link JsonGenerator}
* (and {@link SerializerProvider} if necessary).
*
* Note that implementing this interface binds implementing object
* closely to Jackson API, and that it is often not necessary to do
* so -- if class is a bean, it can be serialized without
* implementing this interface.
*
* Note that while it is possible to just directly implement {@link JsonSerializable},
* actual implementations are strongly recommended to instead extend
* {@link JsonSerializable.Base}.
*/
public interface JsonSerializable
{
/**
* Serialization method called when no additional type information is
* to be included in serialization.
*/
public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException;
/**
* Serialization method called when additional type information is
* expected to be included in serialization, for deserialization to use.
*
* Usually implementation consists of a call to {@link TypeSerializer#writeTypePrefix}
* followed by serialization of contents,
* followed by a call to {@link TypeSerializer#writeTypeSuffix}).
* Details of the type id argument to pass depend on shape of JSON Object used
* (Array, Object or scalar like String/Number/Boolean).
*
* Note that some types (most notably, "natural" types: String, Integer,
* Double and Boolean) never include type information.
*/
public void serializeWithType(JsonGenerator gen, SerializerProvider serializers,
TypeSerializer typeSer) throws IOException;
/**
* Base class with minimal implementation, as well as couple of extension methods
* 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
{
/**
* Method that may be called on instance to determine if it is considered
* "empty" for purposes of serialization filtering or not.
*/
public boolean isEmpty(SerializerProvider serializers) {
return false;
}
}
}
JsonSerializer.java 0000664 0000000 0000000 00000026343 13604243101 0034330 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.IOException;
import java.util.Iterator;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.NameTransformer;
/**
* 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.
*
* 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
* 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.
*
* 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.
*/
public abstract class JsonSerializer
implements JsonFormatVisitable // since 2.1
{
/*
/**********************************************************
/* Fluent factory methods for constructing decorated versions
/**********************************************************
*/
/**
* Method that will return serializer instance that produces
* "unwrapped" serialization, if applicable for type being
* serialized (which is the case for some serializers
* that produce JSON Objects as output).
* If no unwrapped serializer can be constructed, will simply
* return serializer as-is.
*
* Default implementation just returns serializer as-is,
* indicating that no unwrapped variant exists
*
* @param unwrapper Name transformation to use to convert between names
* of unwrapper properties
*/
public JsonSerializer unwrappingSerializer(NameTransformer unwrapper) {
return this;
}
/**
* Method that can be called to try to replace serializer this serializer
* delegates calls to. If not supported (either this serializer does not
* 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();
}
/**
* Mutant factory method that is called if contextual configuration indicates that
* a specific filter (as specified by filterId
) is to be used for
* serialization.
*
* 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;
}
/*
/**********************************************************
/* Serialization methods
/**********************************************************
*/
/**
* Method that can be called to ask implementation to serialize
* values of type this serializer handles.
*
* @param value Value to serialize; can not be null.
* @param gen Generator used to output resulting Json content
* @param serializers Provider that can be used to get serializers for
* serializing Objects value contains, if any.
*/
public abstract void serialize(T value, JsonGenerator gen, SerializerProvider serializers)
throws IOException;
/**
* Method that can be called to ask implementation to serialize
* values of type this serializer handles, using specified type serializer
* for embedding necessary type information.
*
* Default implementation will throw {@link UnsupportedOperationException}
* to indicate that proper type handling needs to be implemented.
*
* For simple datatypes written as a single scalar value (JSON String, Number, Boolean),
* implementation would look like:
*
* // note: method to call depends on whether this type is serialized as JSON scalar, object or Array!
* typeSer.writeTypePrefixForScalar(value, gen);
* serialize(value, gen, provider);
* typeSer.writeTypeSuffixForScalar(value, gen);
*
* and implementations for type serialized as JSON Arrays or Objects would differ slightly,
* as START-ARRAY
/END-ARRAY
and
* START-OBJECT
/END-OBJECT
pairs
* need to be properly handled with respect to serializing of contents.
*
* @param value Value to serialize; can not be null.
* @param gen Generator used to output resulting Json content
* @param serializers Provider that can be used to get serializers for
* serializing Objects value contains, if any.
* @param typeSer Type serializer to use for including type information
*/
public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers,
TypeSerializer typeSer)
throws IOException
{
Class> clz = handledType();
if (clz == null) {
clz = value.getClass();
}
serializers.reportBadDefinition(clz, String.format(
"Type id handling not implemented for type %s (by serializer of type %s)",
clz.getName(), getClass().getName()));
}
/*
/**********************************************************
/* Other accessors
/**********************************************************
*/
/**
* Method for accessing type of Objects this serializer can handle.
* Note that this information is not guaranteed to be exact -- it
* 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.
*
*/
public Class handledType() { return null; }
/**
* 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.
*/
public boolean usesObjectId() {
return false;
}
/**
* Accessor for checking whether this serializer is an
* "unwrapping" serializer; this is necessary to know since
* it may also require caller to suppress writing of the
* leading property name.
*/
public boolean isUnwrappingSerializer() {
return false;
}
/**
* Accessor that can be used to determine if this serializer uses
* another serializer for actual serialization, by delegating
* calls. If so, will return immediate delegate (which itself may
* delegate to further serializers); otherwise will return null.
*
* @return Serializer this serializer delegates calls to, if null;
* null otherwise.
*
* @since 2.1
*/
public JsonSerializer> getDelegatee() {
return null;
}
/**
* Accessor for iterating over logical properties that the type
* handled by this serializer has, from serialization perspective.
* Actual type of properties, if any, will be
* {@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();
}
/*
/**********************************************************
/* Default JsonFormatVisitable implementation
/**********************************************************
*/
/**
* Default implementation simply calls {@link JsonFormatVisitorWrapper#expectAnyFormat(JavaType)}.
*
* @since 2.1
*/
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type)
throws JsonMappingException
{
visitor.expectAnyFormat(type);
}
/*
/**********************************************************
/* Helper class(es)
/**********************************************************
*/
/**
* This marker class is only to be used with annotations, to
* indicate that no serializer is configured .
*
* Specifically, this class is to be used as the marker for
* annotation {@link com.fasterxml.jackson.databind.annotation.JsonSerialize}.
*/
public abstract static class None
extends JsonSerializer { }
}
KeyDeserializer.java 0000664 0000000 0000000 00000001635 13604243101 0034455 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.IOException;
/**
* Abstract class that defines API used for deserializing JSON content
* field names into Java Map keys. These deserializers are only used
* if the Map key class is not String
or Object
.
*/
public abstract class KeyDeserializer
{
/**
* Method called to deserialize a {@link java.util.Map} key from JSON property name.
*/
public abstract Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException;
/**
* This marker class is only to be used with annotations, to
* indicate that no deserializer is configured .
*
* Specifically, this class is to be used as the marker for
* annotation {@link com.fasterxml.jackson.databind.annotation.JsonDeserialize}.
*/
public abstract static class None
extends KeyDeserializer { }
}
MapperFeature.java 0000664 0000000 0000000 00000050665 13604243101 0034131 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.cfg.ConfigFeature;
/**
* Enumeration that defines simple on/off features to set
* for {@link ObjectMapper}, and accessible (but not changeable)
* via {@link ObjectReader} and {@link ObjectWriter} (as well as
* through various convenience methods through context objects).
*
* Note that in addition to being only mutable via {@link ObjectMapper},
* changes only take effect when done before any serialization or
* deserialization calls -- that is, caller must follow
* "configure-then-use" pattern.
*/
public enum MapperFeature implements ConfigFeature
{
/*
/******************************************************
/* General introspection features
/******************************************************
*/
/**
* Feature that determines whether annotation introspection
* is used for configuration; if enabled, configured
* {@link AnnotationIntrospector} will be used: if disabled,
* no annotations are considered.
*
* Feature is enabled by default.
*/
USE_ANNOTATIONS(true),
/**
* Feature that determines whether otherwise regular "getter"
* methods (but only ones that handle Collections and Maps,
* not getters of other type)
* can be used for purpose of getting a reference to a Collection
* and Map to modify the property, without requiring a setter
* method.
* This is similar to how JAXB framework sets Collections and
* Maps: no setter is involved, just setter.
*
* Note that such getters-as-setters methods have lower
* precedence than setters, so they are only used if no
* setter is found for the Map/Collection property.
*
* Feature is enabled by default.
*/
USE_GETTERS_AS_SETTERS(true),
/**
* Feature that determines how transient
modifier for fields
* is handled: if disabled, it is only taken to mean exclusion of the field
* as accessor; if true, it is taken to imply removal of the whole property.
*
* 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,
* constructor parameter or field) or not: if set to true,
* only getters that match a mutator are auto-discovered; if
* false, all auto-detectable getters can be discovered.
*
* Feature is disabled by default.
*/
REQUIRE_SETTERS_FOR_GETTERS(false),
/**
* Feature that determines whether member fields declared as 'final' may
* be auto-detected to be used mutators (used to change value of the logical
* property) or not. If enabled, 'final' access modifier has no effect, and
* such fields may be detected according to usual visibility and inference
* rules; if disabled, such fields are NOT used as mutators except if
* explicitly annotated for such use.
*
* Feature is enabled by default, for backwards compatibility reasons.
*
* @since 2.2
*/
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
/**
* Feature that determines whether member mutators (fields and
* setters) may be "pulled in" even if they are not visible,
* as long as there is a visible accessor (getter or field) with same name.
* For example: field "value" may be inferred as mutator,
* if there is visible or explicitly marked getter "getValue()".
* If enabled, inferring is enabled; otherwise (disabled) only visible and
* explicitly annotated accessors are ever used.
*
* Note that 'getters' are never inferred and need to be either visible (including
* bean-style naming) or explicitly annotated.
*
* Feature is enabled by default.
*
* @since 2.2
*/
INFER_PROPERTY_MUTATORS(true),
/**
* Feature that determines handling of {@code java.beans.ConstructorProperties}
* annotation: when enabled, it is considered as alias of
* {@link com.fasterxml.jackson.annotation.JsonCreator}, to mean that constructor
* should be considered a property-based Creator; when disabled, only constructor
* parameter name information is used, but constructor is NOT considered an explicit
* Creator (although may be discovered as one using other annotations or heuristics).
*
* Feature is mostly used to help inter-operability with frameworks like Lombok
* that may automatically generate {@code ConstructorProperties} annotation
* but without necessarily meaning that constructor should be used as Creator
* for deserialization.
*
* Feature is enabled by default.
*
* @since 2.9
*/
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true),
/*
/******************************************************
/* Access modifier handling
/******************************************************
*/
/**
* Feature that determines whether method and field access
* modifier settings can be overridden when accessing
* properties. If enabled, method
* {@link java.lang.reflect.AccessibleObject#setAccessible}
* may be called to enable access to otherwise unaccessible objects.
*
* Note that this setting may have significant performance implications,
* since access override helps remove costly access checks on each
* and every Reflection access. If you are considering disabling
* this feature, be sure to verify performance consequences if usage
* is performance sensitive.
* Also note that performance effects vary between Java platforms
* (JavaSE vs Android, for example), as well as JDK versions: older
* versions seemed to have more significant performance difference.
*
* Conversely, on some platforms, it may be necessary to disable this feature
* as platform does not allow such calls. For example, when developing
* Applets (or other Java code that runs on tightly restricted sandbox),
* it may be necessary to disable the feature regardless of performance effects.
*
* Feature is enabled by default.
*/
CAN_OVERRIDE_ACCESS_MODIFIERS(true),
/**
* Feature that determines that forces call to
* {@link java.lang.reflect.AccessibleObject#setAccessible} even for
* public
accessors -- that is, even if no such call is
* needed from functionality perspective -- if call is allowed
* (that is, {@link #CAN_OVERRIDE_ACCESS_MODIFIERS} is set to true).
* The main reason to enable this feature is possible performance
* improvement as JDK does not have to perform access checks; these
* checks are otherwise made for all accessors, including public ones,
* and may result in slower Reflection calls. Exact impact (if any)
* depends on Java platform (Java SE, Android) as well as JDK version.
*
* Feature is enabled by default, for legacy reasons (it was the behavior
* until 2.6)
*
* @since 2.7
*/
OVERRIDE_PUBLIC_ACCESS_MODIFIERS(true),
/*
/******************************************************
/* Type-handling features
/******************************************************
*/
/**
* Feature that determines whether the type detection for
* serialization should be using actual dynamic runtime type,
* or declared static type.
* Note that deserialization always uses declared static types
* since no runtime types are available (as we are creating
* instances after using type information).
*
* This global default value can be overridden at class, method
* or field level by using {@link JsonSerialize#typing} annotation
* property.
*
* Feature is disabled by default which means that dynamic runtime types
* are used (instead of declared static types) for serialization.
*/
USE_STATIC_TYPING(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
* is specified via {@code @JsonTypeInfo.defaultImpl} annotation.
*
* Note that feature only has effect on deserialization of regular polymorphic properties:
* it does NOT affect non-polymorphic cases, and is unlikely to work with Default Typing.
*
* Feature is disabled by default for backwards compatibility.
*
* @since 2.10
*/
USE_BASE_TYPE_AS_DEFAULT_IMPL(false),
/*
/******************************************************
/* View-related features
/******************************************************
*/
/**
* Feature that determines whether properties that have no view
* annotations are included in JSON serialization views (see
* {@link com.fasterxml.jackson.annotation.JsonView} for more
* details on JSON Views).
* If enabled, non-annotated properties will be included;
* when disabled, they will be excluded. So this feature
* changes between "opt-in" (feature disabled) and
* "opt-out" (feature enabled) modes.
*
* Default value is enabled, meaning that non-annotated
* properties are included in all views if there is no
* {@link com.fasterxml.jackson.annotation.JsonView} annotation.
*
* Feature is enabled by default.
*/
DEFAULT_VIEW_INCLUSION(true),
/*
/******************************************************
/* Generic output features
/******************************************************
*/
/**
* Feature that defines default property serialization order used
* for POJO fields (note: does not apply to {@link java.util.Map}
* serialization!):
* if enabled, default ordering is alphabetic (similar to
* how {@link com.fasterxml.jackson.annotation.JsonPropertyOrder#alphabetic()}
* works); if disabled, order is unspecified (based on what JDK gives
* us, which may be declaration order, but is not guaranteed).
*
* Note that this is just the default behavior, and can be overridden by
* explicit overrides in classes (for example with
* {@link com.fasterxml.jackson.annotation.JsonPropertyOrder} annotation)
*
* Feature is disabled by default.
*/
SORT_PROPERTIES_ALPHABETICALLY(false),
/*
/******************************************************
/* Name-related features
/******************************************************
*/
/**
* Feature that will allow for more forgiving deserialization of incoming JSON.
* If enabled, the bean properties will be matched using their lower-case equivalents,
* meaning that any case-combination (incoming and matching names are canonicalized
* by lower-casing) should work.
*
* Note that there is additional performance overhead since incoming property
* names need to be lower-cased before comparison, for cases where there are upper-case
* letters. Overhead for names that are already lower-case should be negligible.
*
* Feature is disabled by default.
*
* @since 2.5
*/
ACCEPT_CASE_INSENSITIVE_PROPERTIES(false),
/**
* Feature that determines if Enum deserialization should be case sensitive or not.
* If enabled, Enum deserialization will ignore case, that is, case of incoming String
* value and enum id (depending on other settings, either `name()`, `toString()`, or
* explicit override) do not need to match.
*
* Feature is disabled by default.
*
* @since 2.9
*/
ACCEPT_CASE_INSENSITIVE_ENUMS(false),
/**
* Feature that permits parsing some enumerated text-based value types but ignoring the case
* of the values on deserialization: for example, date/time type deserializers.
* Support for this feature depends on deserializer implementations using it.
*
* Note, however, that regular {@code Enum} types follow {@link #ACCEPT_CASE_INSENSITIVE_ENUMS}
* setting instead.
*
* Feature is disabled by default.
*
* @since 2.10
*/
ACCEPT_CASE_INSENSITIVE_VALUES(false),
/**
* Feature that can be enabled to make property names be
* overridden by wrapper name (usually detected with annotations
* as defined by {@link AnnotationIntrospector#findWrapperName}.
* If enabled, all properties that have associated non-empty Wrapper
* name will use that wrapper name instead of property name.
* 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
* merging is skipped and new value is created (true
) or
* an exception is thrown (false).
*
* Feature is enabled by default, to allow use of merge defaults even in presence
* of some unmergeable properties.
*
* @since 2.9
*/
IGNORE_MERGE_FOR_UNMERGEABLE(true)
;
private final boolean _defaultState;
private final int _mask;
private MapperFeature(boolean defaultState) {
_defaultState = defaultState;
_mask = (1 << ordinal());
}
@Override
public boolean enabledByDefault() { return _defaultState; }
@Override
public int getMask() { return _mask; }
@Override
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
}
MappingIterator.java 0000664 0000000 0000000 00000030756 13604243101 0034475 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
import java.io.Closeable;
import java.io.IOException;
import java.util.*;
import com.fasterxml.jackson.core.*;
/**
* Iterator exposed by {@link ObjectMapper} when binding sequence of
* objects. Extension is done to allow more convenient exposing of
* {@link IOException} (which basic {@link Iterator} does not expose)
*/
public class MappingIterator implements Iterator, Closeable
{
protected final static MappingIterator> EMPTY_ITERATOR =
new MappingIterator(null, null, null, null, false, null);
/*
/**********************************************************
/* State constants
/**********************************************************
*/
/**
* State in which iterator is closed
*/
protected final static int STATE_CLOSED = 0;
/**
* State in which value read failed
*/
protected final static int STATE_NEED_RESYNC = 1;
/**
* State in which no recovery is needed, but "hasNextValue()" needs
* to be called first
*/
protected final static int STATE_MAY_HAVE_VALUE = 2;
/**
* State in which "hasNextValue()" has been succesfully called
* and deserializer can be called to fetch value
*/
protected final static int STATE_HAS_VALUE = 3;
/*
/**********************************************************
/* Configuration
/**********************************************************
*/
/**
* Type to bind individual elements to.
*/
protected final JavaType _type;
/**
* Context for deserialization, needed to pass through to deserializer
*/
protected final DeserializationContext _context;
/**
* Deserializer for individual element values.
*/
protected final JsonDeserializer _deserializer;
/**
* Underlying parser used for reading content to bind. Initialized
* as not null
but set as null
when
* iterator is closed, to denote closing.
*/
protected final JsonParser _parser;
/**
* Context to resynchronize to, in case an exception is encountered
* but caller wants to try to read more elements.
*/
protected final JsonStreamContext _seqContext;
/**
* If not null, "value to update" instead of creating a new instance
* for each call.
*/
protected final T _updatedValue;
/**
* Flag that indicates whether input {@link JsonParser} should be closed
* when we are done or not; generally only called when caller did not
* pass JsonParser.
*/
protected final boolean _closeParser;
/*
/**********************************************************
/* Parsing state
/**********************************************************
*/
/**
* State of the iterator
*/
protected int _state;
/*
/**********************************************************
/* Construction
/**********************************************************
*/
/**
* @param managedParser Whether we "own" the {@link JsonParser} passed or not:
* if true, it was created by {@link ObjectReader} and code here needs to
* close it; if false, it was passed by calling code and should not be
* closed by iterator.
*/
@SuppressWarnings("unchecked")
protected MappingIterator(JavaType type, JsonParser p, DeserializationContext ctxt,
JsonDeserializer> deser,
boolean managedParser, Object valueToUpdate)
{
_type = type;
_parser = p;
_context = ctxt;
_deserializer = (JsonDeserializer) deser;
_closeParser = managedParser;
if (valueToUpdate == null) {
_updatedValue = null;
} else {
_updatedValue = (T) valueToUpdate;
}
/* Ok: one more thing; we may have to skip START_ARRAY, assuming
* "wrapped" sequence; but this is ONLY done for 'managed' parsers
* and never if JsonParser was directly passed by caller (if it
* was, caller must have either positioned it over first token of
* the first element, or cleared the START_ARRAY token explicitly).
* Note, however, that we do not try to guess whether this could be
* an unwrapped sequence of arrays/Lists: we just assume it is wrapped;
* and if not, caller needs to hand us JsonParser instead, pointing to
* the first token of the first element.
*/
if (p == null) { // can this occur?
_seqContext = null;
_state = STATE_CLOSED;
} else {
JsonStreamContext sctxt = p.getParsingContext();
if (managedParser && p.isExpectedStartArrayToken()) {
// If pointing to START_ARRAY, context should be that ARRAY
p.clearCurrentToken();
} else {
// 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.currentToken();
if ((t == JsonToken.START_OBJECT) || (t == JsonToken.START_ARRAY)) {
sctxt = sctxt.getParent();
}
}
_seqContext = sctxt;
_state = STATE_MAY_HAVE_VALUE;
}
}
/**
* Method for getting an "empty" iterator instance: one that never
* has more values; may be freely shared.
*
* @since 2.10 Existed earlier but {@code public} since 2.10
*/
@SuppressWarnings("unchecked")
public static MappingIterator emptyIterator() {
return (MappingIterator) EMPTY_ITERATOR;
}
/*
/**********************************************************
/* Basic iterator impl
/**********************************************************
*/
@Override
public boolean hasNext()
{
try {
return hasNextValue();
} catch (JsonMappingException e) {
return (Boolean) _handleMappingException(e);
} catch (IOException e) {
return (Boolean) _handleIOException(e);
}
}
@SuppressWarnings("unchecked")
@Override
public T next()
{
try {
return nextValue();
} catch (JsonMappingException e) {
return (T) _handleMappingException(e);
} catch (IOException e) {
return (T) _handleIOException(e);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void close() throws IOException {
if (_state != STATE_CLOSED) {
_state = STATE_CLOSED;
if (_parser != null) {
_parser.close();
}
}
}
/*
/**********************************************************
/* Extended API, iteration
/**********************************************************
*/
/**
* Equivalent of {@link #next} but one that may throw checked
* exceptions from Jackson due to invalid input.
*/
public boolean hasNextValue() throws IOException
{
switch (_state) {
case STATE_CLOSED:
return false;
case STATE_NEED_RESYNC:
_resync();
// fall-through
case STATE_MAY_HAVE_VALUE:
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).
if (t == null || t == JsonToken.END_ARRAY) {
_state = STATE_CLOSED;
if (_closeParser && (_parser != null)) {
_parser.close();
}
return false;
}
}
_state = STATE_HAS_VALUE;
return true;
case STATE_HAS_VALUE:
// fall through
}
return true;
}
public T nextValue() throws IOException
{
switch (_state) {
case STATE_CLOSED:
return _throwNoSuchElement();
case STATE_NEED_RESYNC: // fall-through, will do re-sync
case STATE_MAY_HAVE_VALUE:
if (!hasNextValue()) {
return _throwNoSuchElement();
}
break;
case STATE_HAS_VALUE:
break;
}
int nextState = STATE_NEED_RESYNC;
try {
T value;
if (_updatedValue == null) {
value = _deserializer.deserialize(_parser, _context);
} else{
_deserializer.deserialize(_parser, _context, _updatedValue);
value = _updatedValue;
}
nextState = STATE_MAY_HAVE_VALUE;
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.
*/
_parser.clearCurrentToken();
}
}
/**
* Convenience method for reading all entries accessible via
* 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());
}
/**
* Convenience method for reading all entries accessible via
* this iterator
*
* @return List of entries read (same as passed-in argument)
*
* @since 2.2
*/
public > L readAll(L resultList) throws IOException
{
while (hasNextValue()) {
resultList.add(nextValue());
}
return resultList;
}
/**
* Convenience method for reading all entries accessible via
* this iterator
*
* @since 2.5
*/
public > C readAll(C results) throws IOException
{
while (hasNextValue()) {
results.add(nextValue());
}
return results;
}
/*
/**********************************************************
/* Extended API, accessors
/**********************************************************
*/
/**
* Accessor for getting underlying parser this iterator uses.
*
* @since 2.2
*/
public JsonParser getParser() {
return _parser;
}
/**
* 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();
}
/**
* Convenience method, functionally equivalent to:
*
* iterator.getParser().getCurrentLocation()
*
*
* @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
{
final JsonParser p = _parser;
// First, a quick check to see if we might have been lucky and no re-sync needed
if (p.getParsingContext() == _seqContext) {
return;
}
while (true) {
JsonToken t = p.nextToken();
if ((t == JsonToken.END_ARRAY) || (t == JsonToken.END_OBJECT)) {
if (p.getParsingContext() == _seqContext) {
p.clearCurrentToken();
return;
}
} else if ((t == JsonToken.START_ARRAY) || (t == JsonToken.START_OBJECT)) {
p.skipChildren();
} else if (t == null) {
return;
}
}
}
protected R _throwNoSuchElement() {
throw new NoSuchElementException();
}
protected R _handleMappingException(JsonMappingException e) {
throw new RuntimeJsonMappingException(e.getMessage(), e);
}
protected R _handleIOException(IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
MappingJsonFactory.java 0000664 0000000 0000000 00000004437 13604243101 0035142 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind 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;
}
}
jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind/Module.java 0000664 0000000 0000000 00000034022 13604243101 0032662 0 ustar 00root root 0000000 0000000 package com.fasterxml.jackson.databind;
import java.util.Collection;
import com.fasterxml.jackson.core.*;
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.jsontype.NamedType;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.type.TypeModifier;
import java.util.Collections;
/**
* Simple interface for extensions that can be registered with {@link ObjectMapper}
* to provide a well-defined set of extensions to default functionality; such as
* support for new data types.
*/
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
* module that provides them.
*/
public abstract String getModuleName();
/**
* Method that returns version of this module. Can be used by Jackson for
* informational purposes.
*/
@Override
public abstract Version version();
/**
* 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"
*
* Default implementation returns value of class name ({@link Class#getName}).
*
* @since 2.5
*/
public Object getTypeId() {
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);
/**
* Returns the list of dependent modules this module has, if any.
* It is called to let modules register other modules as dependencies.
* Modules returned will be registered before this module is registered,
* in iteration order.
*
* @since 2.10
*/
public Iterable extends Module> getDependencies() {
return Collections.emptyList();
}
/*
/**********************************************************
/* Helper types
/**********************************************************
*/
/**
* Interface Jackson exposes to modules for purpose of registering
* extended functionality.
* Usually implemented by {@link ObjectMapper}, but modules should
* NOT rely on this -- if they do require access to mapper instance,
* they need to call {@link SetupContext#getOwner} method.
*/
public static interface SetupContext
{
/*
/**********************************************************
/* Simple accessors
/**********************************************************
*/
/**
* Method that returns version information about {@link ObjectMapper}
* that implements this context. Modules can use this to choose
* different settings or initialization order; or even decide to fail
* set up completely if version is compatible with module.
*/
public Version getMapperVersion();
/**
* Fallback access method that allows modules to refer to the
* {@link ObjectMapper} 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.
*
* NOTE: use of this method is discouraged, as it allows access to
* things Modules typically should not modify. It is included, however,
* 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
*/
public C getOwner();
/**
* Accessor for finding {@link TypeFactory} that is currently configured
* by the context.
*
* 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 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);
/*
/**********************************************************
/* Mutant accessors
/**********************************************************
*/
/**
* "Mutant 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);
/*
/**********************************************************
/* Handler registration; serializers/deserializers
/**********************************************************
*/
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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 void addTypeModifier(TypeModifier modifier);
/**
* 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 void addValueInstantiators(ValueInstantiators instantiators);
/**
* 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
*/
public void setClassIntrospector(ClassIntrospector ci);
/**
* Method for registering specified {@link AnnotationIntrospector} as the highest
* priority introspector (will be chained with existing introspector(s) which
* will be used as fallbacks for cases this introspector does not handle)
*
* @param ai Annotation introspector to register.
*/
public void insertAnnotationIntrospector(AnnotationIntrospector ai);
/**
* Method for registering specified {@link AnnotationIntrospector} as the lowest
* priority introspector, chained with existing introspector(s) and called
* as fallback for cases not otherwise handled.
*
* @param ai Annotation introspector to register.
*/
public void appendAnnotationIntrospector(AnnotationIntrospector ai);
/**
* Method for registering specified classes as subtypes (of supertype(s)
* they have)
*/
public void registerSubtypes(Class>... subtypes);
/**
* Method for registering specified classes as subtypes (of supertype(s)
* they have), using specified type names.
*/
public void registerSubtypes(NamedType... subtypes);
/**
* Method for registering specified classes as subtypes (of supertype(s)
* they have)
*
* @since 2.9
*/
public void registerSubtypes(Collection> subtypes);
/**
* Method used for defining 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.
*
* Note: mix-ins are registered both for serialization and deserialization
* (which can be different internally).
*
* Note: currently only one set of mix-in annotations can be defined for
* a single class; so if multiple modules register mix-ins, highest
* priority one (last one registered) will have priority over other modules.
*
* @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
*/
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);
}
}
ObjectMapper.java 0000664 0000000 0000000 00000521657 13604243101 0033750 0 ustar 00root root 0000000 0000000 jackson-databind-jackson-databind-2.10.2/src/main/java/com/fasterxml/jackson/databind package com.fasterxml.jackson.databind;
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.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.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.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver;
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
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;
/**
* ObjectMapper provides functionality for reading and writing JSON,
* 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.
* 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.
* Note that although most read and write methods are exposed through this class,
* some of the functionality is only exposed via {@link ObjectReader} and
* {@link ObjectWriter}: specifically, reading/writing of longer sequences of
* values is only available through {@link ObjectReader#readValues(InputStream)}
* and {@link ObjectWriter#writeValues(OutputStream)}.
*
Simplest usage is of form:
final ObjectMapper mapper = new ObjectMapper(); // can use static singleton, inject: just make sure to reuse!
MyValue value = new MyValue();
// ... and configure
File newState = new File("my-stuff.json");
mapper.writeValue(newState, value); // writes JSON serialization of MyValue instance
// or, read
MyValue older = mapper.readValue(new File("my-older-stuff.json"), MyValue.class);
// Or if you prefer JSON Tree representation:
JsonNode root = mapper.readTree(newState);
// 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.
*
*
*
* Note on caching: root-level deserializers are always cached, and accessed
* using full (generics-aware) type information. This is different from
* caching of referenced types, which is more limited and is done only
* for a subset of all deserializer types. The main reason for difference
* is that at root-level there is no incoming reference (and hence no
* referencing property, no referral information or annotations to
* 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
{
private static final long serialVersionUID = 2L; // as of 2.9
/*
/**********************************************************
/* Helper classes, enums
/**********************************************************
*/
/**
* Enumeration used with {@link ObjectMapper#activateDefaultTyping(PolymorphicTypeValidator)}
* 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, make sure to {@code activateDefaultTyping(...)}
* methods that take {@link PolymorphicTypeValidator} that limits applicability
* to known trusted types.
*/
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,
/**
* 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) that
* can be correctly inferred from JSON, and primitives (which
* can not be polymorphic either). Typing is also enabled for
* all array types.
*
* Note that the only known use case for this setting is for serialization
* when passing instances of final class, and base type is not
* separately specified.
*
* @since 2.10
*/
EVERYTHING
}
/**
* Customized {@link TypeResolverBuilder} that provides type resolver builders
* used with so-called "default typing"
* (see {@link ObjectMapper#activateDefaultTyping(PolymorphicTypeValidator)} 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
{
private static final long serialVersionUID = 1L;
/**
* Definition of what types is this default typer valid for.
*/
protected final DefaultTyping _appliesFor;
/**
* {@link PolymorphicTypeValidator} top use for validating that the subtypes
* resolved are valid for use (usually to protect against possible
* security issues)
*
* @since 2.10
*/
protected final PolymorphicTypeValidator _subtypeValidator;
/**
* @deprecated Since 2.10
*/
@Deprecated // since 2.10
public DefaultTypeResolverBuilder(DefaultTyping t) {
this(t, LaissezFaireSubTypeValidator.instance);
}
/**
* @since 2.10
*/
public DefaultTypeResolverBuilder(DefaultTyping t, PolymorphicTypeValidator ptv) {
_appliesFor = Objects.requireNonNull(t, "Can not pass `null` DefaultTyping");
_subtypeValidator = Objects.requireNonNull(ptv, "Can not pass `null` PolymorphicTypeValidator");
}
/**
* @since 2.10
*/
public static DefaultTypeResolverBuilder construct(DefaultTyping t,
PolymorphicTypeValidator ptv) {
return new DefaultTypeResolverBuilder(t, ptv);
}
@Override // since 2.10
public PolymorphicTypeValidator subTypeValidator(MapperConfig> config) {
return _subtypeValidator;
}
@Override
public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
JavaType baseType, Collection subtypes)
{
return useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes) : null;
}
@Override
public TypeSerializer buildTypeSerializer(SerializationConfig config,
JavaType baseType, Collection subtypes)
{
return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null;
}
/**
* 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;
}
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());
case EVERYTHING:
// So, excluding primitives (handled earlier) and "Natural types" (handled
// before this method is called), applied to everything
return true;
default:
case JAVA_LANG_OBJECT:
return t.isJavaLangObject();
}
}
}
/*
/**********************************************************
/* Internal constants, singletons
/**********************************************************
*/
// 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
LaissezFaireSubTypeValidator.instance
);
/*
/**********************************************************
/* Configuration settings, shared
/**********************************************************
*/
/**
* Factory used to create {@link JsonParser} and {@link JsonGenerator}
* instances as necessary.
*/
protected final JsonFactory _jsonFactory;
/**
* 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;
/**
* 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;
/*
/**********************************************************
/* 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.
*
* Note: while serializers are only exposed {@link SerializerProvider},
* mappers and readers need to access additional API defined by
* {@link DefaultSerializerProvider}
*/
protected DefaultSerializerProvider _serializerProvider;
/**
* Serializer factory used for constructing serializers.
*/
protected SerializerFactory _serializerFactory;
/*
/**********************************************************
/* 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
/**********************************************************
*/
/**
* 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
*/
protected Set _registeredModuleTypes;
/*
/**********************************************************
/* Caching
/**********************************************************
*/
/* Note: handling of serializers and deserializers is not symmetric;
* and as a result, only root-level deserializers can be cached here.
* This is mostly because typing and resolution for deserializers is
* fully static; whereas it is quite dynamic for serialization.
*/
/**
* We will use a separate main-level Map for keeping track
* of root-level deserializers. This is where most successful
* cache lookups get resolved.
* Map will contain resolvers for all kinds of types, including
* container types: this is different from the component cache
* which will only cache bean deserializers.
*
* Given that we don't expect much concurrency for additions
* (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
* no type information is needed for base type), or type-wrapped
* deserializers (if it is needed)
*/
final protected ConcurrentHashMap> _rootDeserializers
= new ConcurrentHashMap>(64, 0.6f, 2);
/*
/**********************************************************
/* Life-cycle: constructing instance
/**********************************************************
*/
/**
* 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.
*/
public ObjectMapper() {
this(null, null, null);
}
/**
* Constructs instance that uses specified {@link JsonFactory}
* for constructing necessary {@link JsonParser}s and/or
* {@link JsonGenerator}s.
*/
public ObjectMapper(JsonFactory jf) {
this(jf, null, null);
}
/**
* Copy-constructor, mostly used to support {@link #copy}.
*
* @since 2.1
*/
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);
}
}
/**
* Constructs instance that uses specified {@link JsonFactory}
* 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
*/
protected ClassIntrospector defaultClassIntrospector() {
return new BasicClassIntrospector();
}
/*
/**********************************************************
/* 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
*/
public ObjectMapper copy() {
_checkInvalidCopy(ObjectMapper.class);
return new ObjectMapper(this);
}
/**
* @since 2.1
*/
protected void _checkInvalidCopy(Class> exp)
{
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");
}
}
/*
/**********************************************************
/* 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);
}
/**
* 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);
}
/**
* Factory method sub-classes must override, to produce {@link ObjectWriter}
* instances of proper sub-type
*
* @since 2.5
*/
protected ObjectWriter _newWriter(SerializationConfig config) {
return new ObjectWriter(this, config);
}
/**
* Factory method sub-classes must override, to produce {@link ObjectWriter}
* instances of proper sub-type
*
* @since 2.5
*/
protected ObjectWriter _newWriter(SerializationConfig config, FormatSchema schema) {
return new ObjectWriter(this, config, schema);
}
/**
* 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);
}
/*
/**********************************************************
/* Versioned impl
/**********************************************************
*/
/**
* Method that will return version information stored in and read from jar
* that contains this class.
*/
@Override
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)
{
_assertNotNull("module", module);
// 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");
}
// [databind#2432]: Modules may depend on other modules; if so, register those first
for (Module dep : module.getDependencies()) {
registerModule(dep);
}
// then module itself
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;
}
}
}
// 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)
{
_assertNotNull("modules", 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 (_registeredModuleTypes == null) ?
Collections.emptySet() : 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