package com.fasterxml.jackson.databind;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.cfg.ContextAttributes;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.*;
import com.fasterxml.jackson.databind.ser.impl.FailingSerializer;
import com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap;
import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer;
import com.fasterxml.jackson.databind.ser.impl.UnknownSerializer;
import com.fasterxml.jackson.databind.ser.impl.WritableObjectId;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.ClassUtil;
Class that defines API used by ObjectMapper
and JsonSerializer
s to obtain serializers capable of serializing instances of specific types; as well as the default implementation of the functionality. Provider handles caching aspects of serializer handling; all construction details are delegated to SerializerFactory
instance.
Object life-cycle is such that an initial instance ("blueprint") is created and referenced by ObjectMapper
and ObjectWriter
intances; but for actual usage, a configured instance is created by using a create method in sub-class DefaultSerializerProvider
. Only this instance can be used for actual serialization calls; blueprint object is only to be used for creating instances.
/**
* Class that defines API used by {@link ObjectMapper} and
* {@link JsonSerializer}s to obtain serializers capable of serializing
* instances of specific types; as well as the default implementation
* of the functionality.
*<p>
* Provider handles caching aspects of serializer handling; all construction
* details are delegated to {@link SerializerFactory} instance.
*<p>
* Object life-cycle is such that an initial instance ("blueprint") is created
* and referenced by {@link ObjectMapper} and {@link ObjectWriter} intances;
* but for actual usage, a configured instance is created by using
* a create method in sub-class
* {@link com.fasterxml.jackson.databind.ser.DefaultSerializerProvider}.
* Only this instance can be used for actual serialization calls; blueprint
* object is only to be used for creating instances.
*/
public abstract class SerializerProvider
extends DatabindContext
{
Setting for determining whether mappings for "unknown classes" should be
cached for faster resolution. Usually this isn't needed, but maybe it
is in some cases?
/**
* Setting for determining whether mappings for "unknown classes" should be
* cached for faster resolution. Usually this isn't needed, but maybe it
* is in some cases?
*/
protected final static boolean CACHE_UNKNOWN_MAPPINGS = false;
public final static JsonSerializer<Object> DEFAULT_NULL_KEY_SERIALIZER =
new FailingSerializer("Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)");
Placeholder serializer used when java.lang.Object
typed property
is marked to be serialized.
NOTE: starting with 2.6, this instance is NOT used for any other types, and
separate instances are constructed for "empty" Beans.
NOTE: changed to protected
for 2.3; no need to be publicly available.
/**
* Placeholder serializer used when <code>java.lang.Object</code> typed property
* is marked to be serialized.
*<br>
* NOTE: starting with 2.6, this instance is NOT used for any other types, and
* separate instances are constructed for "empty" Beans.
*<p>
* NOTE: changed to <code>protected</code> for 2.3; no need to be publicly available.
*/
protected final static JsonSerializer<Object> DEFAULT_UNKNOWN_SERIALIZER = new UnknownSerializer();
/*
/**********************************************************
/* Configuration, general
/**********************************************************
*/
Serialization configuration to use for serialization processing.
/**
* Serialization configuration to use for serialization processing.
*/
final protected SerializationConfig _config;
View used for currently active serialization, if any.
Only set for non-blueprint instances.
/**
* View used for currently active serialization, if any.
* Only set for non-blueprint instances.
*/
final protected Class<?> _serializationView;
/*
/**********************************************************
/* Configuration, factories
/**********************************************************
*/
Factory used for constructing actual serializer instances.
Only set for non-blueprint instances.
/**
* Factory used for constructing actual serializer instances.
* Only set for non-blueprint instances.
*/
final protected SerializerFactory _serializerFactory;
/*
/**********************************************************
/* Helper objects for caching, reuse
/**********************************************************
*/
Cache for doing type-to-value-serializer lookups.
/**
* Cache for doing type-to-value-serializer lookups.
*/
final protected SerializerCache _serializerCache;
Lazily-constructed holder for per-call attributes.
Only set for non-blueprint instances.
Since: 2.3
/**
* Lazily-constructed holder for per-call attributes.
* Only set for non-blueprint instances.
*
* @since 2.3
*/
protected transient ContextAttributes _attributes;
/*
/**********************************************************
/* Configuration, specialized serializers
/**********************************************************
*/
Serializer that gets called for values of types for which no
serializers can be constructed.
The default serializer will simply thrown an exception.
/**
* Serializer that gets called for values of types for which no
* serializers can be constructed.
*<p>
* The default serializer will simply thrown an exception.
*/
protected JsonSerializer<Object> _unknownTypeSerializer = DEFAULT_UNKNOWN_SERIALIZER;
Serializer used to output non-null keys of Maps (which will get
output as JSON Objects), if not null; if null, us the standard
default key serializer.
/**
* Serializer used to output non-null keys of Maps (which will get
* output as JSON Objects), if not null; if null, us the standard
* default key serializer.
*/
protected JsonSerializer<Object> _keySerializer;
Serializer used to output a null value. Default implementation writes nulls using JsonGenerator.writeNull
. /**
* Serializer used to output a null value. Default implementation
* writes nulls using {@link JsonGenerator#writeNull}.
*/
protected JsonSerializer<Object> _nullValueSerializer = NullSerializer.instance;
Serializer used to (try to) output a null key, due to an entry of Map
having null key. The default implementation will throw an exception if this happens; alternative implementation (like one that would write an Empty String) can be defined. /**
* Serializer used to (try to) output a null key, due to an entry of
* {@link java.util.Map} having null key.
* The default implementation will throw an exception if this happens;
* alternative implementation (like one that would write an Empty String)
* can be defined.
*/
protected JsonSerializer<Object> _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER;
/*
/**********************************************************
/* State, for non-blueprint instances: generic
/**********************************************************
*/
For fast lookups, we will have a local non-shared read-only
map that contains serializers previously fetched.
/**
* For fast lookups, we will have a local non-shared read-only
* map that contains serializers previously fetched.
*/
protected final ReadOnlyClassToSerializerMap _knownSerializers;
Lazily acquired and instantiated formatter object: initialized
first time it is needed, reused afterwards. Used via instances
(not blueprints), so that access need not be thread-safe.
/**
* Lazily acquired and instantiated formatter object: initialized
* first time it is needed, reused afterwards. Used via instances
* (not blueprints), so that access need not be thread-safe.
*/
protected DateFormat _dateFormat;
Flag set to indicate that we are using vanilla null value serialization
Since: 2.3
/**
* Flag set to indicate that we are using vanilla null value serialization
*
* @since 2.3
*/
protected final boolean _stdNullValueSerializer;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
Constructor for creating master (or "blue-print") provider object,
which is only used as the template for constructing per-binding
instances.
/**
* Constructor for creating master (or "blue-print") provider object,
* which is only used as the template for constructing per-binding
* instances.
*/
public SerializerProvider()
{
_config = null;
_serializerFactory = null;
_serializerCache = new SerializerCache();
// Blueprints doesn't have access to any serializers...
_knownSerializers = null;
_serializationView = null;
_attributes = null;
// not relevant for blueprint instance, could set either way:
_stdNullValueSerializer = true;
}
"Copy-constructor", used by sub-classes when creating actual non-blueprint
instances to use.
Params: - src – Blueprint object used as the baseline for this instance
/**
* "Copy-constructor", used by sub-classes when creating actual non-blueprint
* instances to use.
*
* @param src Blueprint object used as the baseline for this instance
*/
protected SerializerProvider(SerializerProvider src,
SerializationConfig config, SerializerFactory f)
{
_serializerFactory = f;
_config = config;
_serializerCache = src._serializerCache;
_unknownTypeSerializer = src._unknownTypeSerializer;
_keySerializer = src._keySerializer;
_nullValueSerializer = src._nullValueSerializer;
_nullKeySerializer = src._nullKeySerializer;
_stdNullValueSerializer = (_nullValueSerializer == DEFAULT_NULL_KEY_SERIALIZER);
_serializationView = config.getActiveView();
_attributes = config.getAttributes();
/* Non-blueprint instances do have a read-only map; one that doesn't
* need synchronization for lookups.
*/
_knownSerializers = _serializerCache.getReadOnlyLookupMap();
}
Copy-constructor used when making a copy of a blueprint instance.
Since: 2.5
/**
* Copy-constructor used when making a copy of a blueprint instance.
*
* @since 2.5
*/
protected SerializerProvider(SerializerProvider src)
{
// since this is assumed to be a blue-print instance, many settings missing:
_config = null;
_serializationView = null;
_serializerFactory = null;
_knownSerializers = null;
// and others initialized to default empty state
_serializerCache = new SerializerCache();
_unknownTypeSerializer = src._unknownTypeSerializer;
_keySerializer = src._keySerializer;
_nullValueSerializer = src._nullValueSerializer;
_nullKeySerializer = src._nullKeySerializer;
_stdNullValueSerializer = src._stdNullValueSerializer;
}
/*
/**********************************************************
/* Methods for configuring default settings
/**********************************************************
*/
Method that can be used to specify serializer that will be
used to write JSON property names matching null keys for Java
Maps (which will throw an exception if try write such property
name)
/**
* Method that can be used to specify serializer that will be
* used to write JSON property names matching null keys for Java
* Maps (which will throw an exception if try write such property
* name)
*/
public void setDefaultKeySerializer(JsonSerializer<Object> ks)
{
if (ks == null) {
throw new IllegalArgumentException("Cannot pass null JsonSerializer");
}
_keySerializer = ks;
}
Method that can be used to specify serializer that will be
used to write JSON values matching Java null values
instead of default one (which simply writes JSON null).
Note that you can get finer control over serializer to use by overriding findNullValueSerializer
, which gets called once per each property.
/**
* Method that can be used to specify serializer that will be
* used to write JSON values matching Java null values
* instead of default one (which simply writes JSON null).
*<p>
* Note that you can get finer control over serializer to use by overriding
* {@link #findNullValueSerializer}, which gets called once per each
* property.
*/
public void setNullValueSerializer(JsonSerializer<Object> nvs)
{
if (nvs == null) {
throw new IllegalArgumentException("Cannot pass null JsonSerializer");
}
_nullValueSerializer = nvs;
}
Method that can be used to specify serializer to use for serializing
all non-null JSON property names, unless more specific key serializer
is found (i.e. if not custom key serializer has been registered for
Java type).
Note that key serializer registration are different from value serializer
registrations.
/**
* Method that can be used to specify serializer to use for serializing
* all non-null JSON property names, unless more specific key serializer
* is found (i.e. if not custom key serializer has been registered for
* Java type).
*<p>
* Note that key serializer registration are different from value serializer
* registrations.
*/
public void setNullKeySerializer(JsonSerializer<Object> nks)
{
if (nks == null) {
throw new IllegalArgumentException("Cannot pass null JsonSerializer");
}
_nullKeySerializer = nks;
}
/*
/**********************************************************
/* DatabindContext implementation (and closely related but ser-specific)
/**********************************************************
*/
Method for accessing configuration for the serialization processing.
/**
* Method for accessing configuration for the serialization processing.
*/
@Override
public final SerializationConfig getConfig() { return _config; }
@Override
public final AnnotationIntrospector getAnnotationIntrospector() {
return _config.getAnnotationIntrospector();
}
@Override
public final TypeFactory getTypeFactory() {
return _config.getTypeFactory();
}
@Override // since 2.11
public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
throws IllegalArgumentException
{
if (baseType.hasRawClass(subclass)) {
return baseType;
}
// Need little bit different handling due to [databind#2632]; pass `true` for
// "relaxed" type assingment checks.
return getConfig().getTypeFactory().constructSpecializedType(baseType, subclass, true);
}
@Override
public final Class<?> getActiveView() { return _serializationView; }
Deprecated: Since 2.2, use getActiveView
instead.
/**
* @deprecated Since 2.2, use {@link #getActiveView} instead.
*/
@Deprecated
public final Class<?> getSerializationView() { return _serializationView; }
@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);
}
Since: 2.8
/**
* @since 2.8
*/
public final JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType) {
return _config.getDefaultPropertyInclusion(baseType);
}
Method for accessing default Locale to use: convenience method for
getConfig().getLocale();
/**
* Method for accessing default Locale to use: convenience method for
*<pre>
* getConfig().getLocale();
*</pre>
*/
@Override
public Locale getLocale() {
return _config.getLocale();
}
Method for accessing default TimeZone to use: convenience method for
getConfig().getTimeZone();
/**
* Method for accessing default TimeZone to use: convenience method for
*<pre>
* getConfig().getTimeZone();
*</pre>
*/
@Override
public TimeZone getTimeZone() {
return _config.getTimeZone();
}
/*
/**********************************************************
/* Generic attributes (2.3+)
/**********************************************************
*/
@Override
public Object getAttribute(Object key) {
return _attributes.getAttribute(key);
}
@Override
public SerializerProvider setAttribute(Object key, Object value)
{
_attributes = _attributes.withPerCallAttribute(key, value);
return this;
}
/*
/**********************************************************
/* Access to general configuration
/**********************************************************
*/
Convenience method for checking whether specified serialization
feature is enabled or not.
Shortcut for:
getConfig().isEnabled(feature);
/**
* Convenience method for checking whether specified serialization
* feature is enabled or not.
* Shortcut for:
*<pre>
* getConfig().isEnabled(feature);
*</pre>
*/
public final boolean isEnabled(SerializationFeature feature) {
return _config.isEnabled(feature);
}
"Bulk" access method for checking that all features specified by
mask are enabled.
Since: 2.3
/**
* "Bulk" access method for checking that all features specified by
* mask are enabled.
*
* @since 2.3
*/
public final boolean hasSerializationFeatures(int featureMask) {
return _config.hasSerializationFeatures(featureMask);
}
Convenience method for accessing provider to find serialization filters used,
equivalent to calling:
getConfig().getFilterProvider();
/**
* Convenience method for accessing provider to find serialization filters used,
* equivalent to calling:
*<pre>
* getConfig().getFilterProvider();
*</pre>
*/
public final FilterProvider getFilterProvider() {
return _config.getFilterProvider();
}
NOTE: current implementation simply returns `null` as generator is not yet
assigned to this provider.
Since: 2.8
/**
*<p>
* NOTE: current implementation simply returns `null` as generator is not yet
* assigned to this provider.
*
* @since 2.8
*/
public JsonGenerator getGenerator() {
return null;
}
/*
/**********************************************************
/* Access to Object Id aspects
/**********************************************************
*/
Method called to find the Object Id for given POJO, if one
has been generated. Will always return a non-null Object;
contents vary depending on whether an Object Id already
exists or not.
/**
* Method called to find the Object Id for given POJO, if one
* has been generated. Will always return a non-null Object;
* contents vary depending on whether an Object Id already
* exists or not.
*/
public abstract WritableObjectId findObjectId(Object forPojo,
ObjectIdGenerator<?> generatorType);
/*
/**********************************************************
/* General serializer locating functionality
/**********************************************************
*/
Method called to get hold of a serializer for a value of given type;
or if no such serializer can be found, a default handler (which
may do a best-effort generic serialization or just simply
throw an exception when invoked).
Note: this method is only called for non-null values; not for keys
or null values. For these, check out other accessor methods.
Note that serializers produced should NOT handle polymorphic serialization aspects; separate TypeSerializer
is to be constructed by caller if and as necessary.
Throws: - JsonMappingException – if there are fatal problems with
accessing suitable serializer; including that of not
finding any serializer
/**
* Method called to get hold of a serializer for a value of given type;
* or if no such serializer can be found, a default handler (which
* may do a best-effort generic serialization or just simply
* throw an exception when invoked).
*<p>
* Note: this method is only called for non-null values; not for keys
* or null values. For these, check out other accessor methods.
*<p>
* Note that serializers produced should NOT handle polymorphic serialization
* aspects; separate {@link TypeSerializer} is to be constructed by caller
* if and as necessary.
*
* @throws JsonMappingException if there are fatal problems with
* accessing suitable serializer; including that of not
* finding any serializer
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findValueSerializer(Class<?> valueType, BeanProperty property)
throws JsonMappingException
{
// Fast lookup from local lookup thingy works?
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
// If not, maybe shared map already has it?
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
// ... possibly as fully typed?
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
if (ser == null) {
// If neither, must create
ser = _createAndCacheUntypedSerializer(valueType);
// Not found? Must use the unknown type serializer, which will report error later on
if (ser == null) {
ser = getUnknownTypeSerializer(valueType);
// Should this be added to lookups?
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
}
// at this point, resolution has occured, but not contextualization
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
Similar to findValueSerializer(Class<?>, BeanProperty)
, but takes full generics-aware type instead of raw class. This is necessary for accurate handling of external type information, to handle polymorphic types.
Note: this call will also contextualize serializer before returning it.
Params: - property – When creating secondary serializers, property for which
serializer is needed: annotations of the property (or bean that contains it)
may be checked to create contextual serializers.
/**
* Similar to {@link #findValueSerializer(Class,BeanProperty)}, but takes
* full generics-aware type instead of raw class.
* This is necessary for accurate handling of external type information,
* to handle polymorphic types.
*<p>
* Note: this call will also contextualize serializer before returning it.
*
* @param property When creating secondary serializers, property for which
* serializer is needed: annotations of the property (or bean that contains it)
* may be checked to create contextual serializers.
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProperty property)
throws JsonMappingException
{
if (valueType == null) {
reportMappingProblem("Null passed for `valueType` of `findValueSerializer()`");
}
// (see comments from above method)
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType.getRawClass());
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
Method variant used when we do NOT want contextualization to happen; it will need
to be handled at a later point, but caller wants to be able to do that
as needed; sometimes to avoid infinite loops
Since: 2.5
/**
* Method variant used when we do NOT want contextualization to happen; it will need
* to be handled at a later point, but caller wants to be able to do that
* as needed; sometimes to avoid infinite loops
*
* @since 2.5
*/
public JsonSerializer<Object> findValueSerializer(Class<?> valueType) throws JsonMappingException
{
// (see comments from above method)
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType);
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
}
}
}
}
return ser;
}
Method variant used when we do NOT want contextualization to happen; it will need
to be handled at a later point, but caller wants to be able to do that
as needed; sometimes to avoid infinite loops
Since: 2.5
/**
* Method variant used when we do NOT want contextualization to happen; it will need
* to be handled at a later point, but caller wants to be able to do that
* as needed; sometimes to avoid infinite loops
*
* @since 2.5
*/
public JsonSerializer<Object> findValueSerializer(JavaType valueType)
throws JsonMappingException
{
// (see comments from above method)
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType.getRawClass());
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
}
}
}
return ser;
}
Similar to findValueSerializer(JavaType, BeanProperty)
, but used when finding "primary" property value serializer (one directly handling value of the property). Difference has to do with contextual resolution, and method(s) called: this method should only be called when caller is certain that this is the primary property value serializer. Params: - valueType – Type of values to serialize
- property – Property that is being handled; will never be null, and its
type has to match
valueType
parameter.
Since: 2.3
/**
* Similar to {@link #findValueSerializer(JavaType, BeanProperty)}, but used
* when finding "primary" property value serializer (one directly handling
* value of the property). Difference has to do with contextual resolution,
* and method(s) called: this method should only be called when caller is
* certain that this is the primary property value serializer.
*
* @param valueType Type of values to serialize
* @param property Property that is being handled; will never be null, and its
* type has to match <code>valueType</code> parameter.
*
* @since 2.3
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findPrimaryPropertySerializer(JavaType valueType, BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType.getRawClass());
// Should this be added to lookups?
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
return (JsonSerializer<Object>) handlePrimaryContextualization(ser, property);
}
Since: 2.3
/**
* See {@link #findPrimaryPropertySerializer(JavaType, BeanProperty)}
*
* @since 2.3
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findPrimaryPropertySerializer(Class<?> valueType,
BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType);
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
}
return (JsonSerializer<Object>) handlePrimaryContextualization(ser, property);
}
Alternative to findPrimaryPropertySerializer(JavaType, BeanProperty)
called not for primary value, but "content" of such primary serializer: element of an array or Collection
, value of Map
entry and so on. This means that property
passed (if any) does NOT represent value for which serializer is requested but its secondary type (or secondary type of that type, recursively).
Serializer returned SHOULD NOT handle type information; caller will (have to) add
suitable wrapping if necessary.
Note: this call will also contextualize serializer (call createContextual()
before returning it, if applicable (implements ContextualSerializer
)
Params: - valueType – Type of values to serialize
- property – Property that indirectly refers to value being serialized (optional, may be
null
for root level serializers)
Since: 2.11
/**
* Alternative to {@link #findPrimaryPropertySerializer(JavaType, BeanProperty)} called not
* for primary value, but "content" of such primary serializer: element of an array or
* {@link java.util.Collection}, value of {@link java.util.Map} entry and so on.
* This means that {@code property} passed (if any) does NOT represent value for which
* serializer is requested but its secondary type (or secondary type of that type,
* recursively).
*<p>
* Serializer returned SHOULD NOT handle type information; caller will (have to) add
* suitable wrapping if necessary.
*<p>
* Note: this call will also contextualize serializer (call {@code createContextual()}
* before returning it, if applicable (implements {@code ContextualSerializer})
*
* @param valueType Type of values to serialize
* @param property Property that indirectly refers to value being serialized (optional,
* may be {@code null} for root level serializers)
*
* @since 2.11
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findContentValueSerializer(JavaType valueType, BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType.getRawClass());
// Should this be added to lookups?
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
Since: 2.11
/**
* See {@link #findContentValueSerializer(JavaType, BeanProperty)}.
*
* @since 2.11
*/
@SuppressWarnings("unchecked")
public JsonSerializer<Object> findContentValueSerializer(Class<?> valueType,
BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(valueType);
if (ser == null) {
ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType));
if (ser == null) {
ser = _createAndCacheUntypedSerializer(valueType);
if (ser == null) {
ser = getUnknownTypeSerializer(valueType);
if (CACHE_UNKNOWN_MAPPINGS) {
_serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this);
}
return ser;
}
}
}
}
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
Method called to locate regular serializer, matching type serializer,
and if both found, wrap them in a serializer that calls both in correct
sequence. This method is currently only used for root-level serializer
handling to allow for simpler caching. A call can always be replaced
by equivalent calls to access serializer and type serializer separately.
Params: - valueType – Type for purpose of locating a serializer; usually dynamic
runtime type, but can also be static declared type, depending on configuration
- cache – Whether resulting value serializer should be cached or not; this is just
a hint
- property – When creating secondary serializers, property for which
serializer is needed: annotations of the property (or bean that contains it)
may be checked to create contextual serializers.
/**
* Method called to locate regular serializer, matching type serializer,
* and if both found, wrap them in a serializer that calls both in correct
* sequence. This method is currently only used for root-level serializer
* handling to allow for simpler caching. A call can always be replaced
* by equivalent calls to access serializer and type serializer separately.
*
* @param valueType Type for purpose of locating a serializer; usually dynamic
* runtime type, but can also be static declared type, depending on configuration
* @param cache Whether resulting value serializer should be cached or not; this is just
* a hint
* @param property When creating secondary serializers, property for which
* serializer is needed: annotations of the property (or bean that contains it)
* may be checked to create contextual serializers.
*/
public JsonSerializer<Object> findTypedValueSerializer(Class<?> valueType,
boolean cache, BeanProperty property)
throws JsonMappingException
{
// Two-phase lookups; local non-shared cache, then shared:
JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// If not, maybe shared map already has it?
ser = _serializerCache.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// Well, let's just compose from pieces:
ser = findValueSerializer(valueType, property);
TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config,
_config.constructType(valueType));
if (typeSer != null) {
typeSer = typeSer.forProperty(property);
ser = new TypeWrappedSerializer(typeSer, ser);
}
if (cache) {
_serializerCache.addTypedSerializer(valueType, ser);
}
return ser;
}
Method called to locate regular serializer, matching type serializer,
and if both found, wrap them in a serializer that calls both in correct
sequence. This method is currently only used for root-level serializer
handling to allow for simpler caching. A call can always be replaced
by equivalent calls to access serializer and type serializer separately.
Params: - valueType – Declared type of value being serialized (which may not
be actual runtime type); used for finding both value serializer and
type serializer to use for adding polymorphic type (if any)
- cache – Whether resulting value serializer should be cached or not; this is just
a hint
- property – When creating secondary serializers, property for which
serializer is needed: annotations of the property (or bean that contains it)
may be checked to create contextual serializers.
/**
* Method called to locate regular serializer, matching type serializer,
* and if both found, wrap them in a serializer that calls both in correct
* sequence. This method is currently only used for root-level serializer
* handling to allow for simpler caching. A call can always be replaced
* by equivalent calls to access serializer and type serializer separately.
*
* @param valueType Declared type of value being serialized (which may not
* be actual runtime type); used for finding both value serializer and
* type serializer to use for adding polymorphic type (if any)
* @param cache Whether resulting value serializer should be cached or not; this is just
* a hint
* @param property When creating secondary serializers, property for which
* serializer is needed: annotations of the property (or bean that contains it)
* may be checked to create contextual serializers.
*/
public JsonSerializer<Object> findTypedValueSerializer(JavaType valueType, boolean cache,
BeanProperty property)
throws JsonMappingException
{
// Two-phase lookups; local non-shared cache, then shared:
JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// If not, maybe shared map already has it?
ser = _serializerCache.typedValueSerializer(valueType);
if (ser != null) {
return ser;
}
// Well, let's just compose from pieces:
ser = findValueSerializer(valueType, property);
TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, valueType);
if (typeSer != null) {
typeSer = typeSer.forProperty(property);
ser = new TypeWrappedSerializer(typeSer, ser);
}
if (cache) {
_serializerCache.addTypedSerializer(valueType, ser);
}
return ser;
}
Method called to get the TypeSerializer
to use for including Type Id necessary for serializing for the given Java class. Useful for schema generators. Since: 2.6
/**
* Method called to get the {@link TypeSerializer} to use for including Type Id necessary
* for serializing for the given Java class.
* Useful for schema generators.
*
* @since 2.6
*/
public TypeSerializer findTypeSerializer(JavaType javaType) throws JsonMappingException {
return _serializerFactory.createTypeSerializer(_config, javaType);
}
Method called to get the serializer to use for serializing non-null Map keys. Separation from regular findValueSerializer
method is because actual write method must be different (@link JsonGenerator#writeFieldName}; but also since behavior for some key types may differ.
Note that the serializer itself can be called with instances
of any Java object, but not nulls.
/**
* Method called to get the serializer to use for serializing
* non-null Map keys. Separation from regular
* {@link #findValueSerializer} method is because actual write
* method must be different (@link JsonGenerator#writeFieldName};
* but also since behavior for some key types may differ.
*<p>
* Note that the serializer itself can be called with instances
* of any Java object, but not nulls.
*/
public JsonSerializer<Object> findKeySerializer(JavaType keyType, BeanProperty property)
throws JsonMappingException
{
JsonSerializer<Object> ser = _serializerFactory.createKeySerializer(this, keyType, _keySerializer);
// 25-Feb-2011, tatu: As per [JACKSON-519], need to ensure contextuality works here, too
return _handleContextualResolvable(ser, property);
}
Since: 2.7
/**
* @since 2.7
*/
public JsonSerializer<Object> findKeySerializer(Class<?> rawKeyType, BeanProperty property)
throws JsonMappingException
{
return findKeySerializer(_config.constructType(rawKeyType), property);
}
/*
/********************************************************
/* Accessors for specialized serializers
/********************************************************
*/
Since: 2.0
/**
* @since 2.0
*/
public JsonSerializer<Object> getDefaultNullKeySerializer() {
return _nullKeySerializer;
}
Since: 2.0
/**
* @since 2.0
*/
public JsonSerializer<Object> getDefaultNullValueSerializer() {
return _nullValueSerializer;
}
/**
* Method called to get the serializer to use for serializing
* Map keys that are nulls: this is needed since JSON does not allow
* any non-String value as key, including null.
*<p>
* Typically, returned serializer
* will either throw an exception, or use an empty String; but
* other behaviors are possible.
*/
Method called to find a serializer to use for null values for given
declared type. Note that type is completely based on declared type,
since nulls in Java have no type and thus runtime type cannot be
determined.
Since: 2.0
/**
* Method called to find a serializer to use for null values for given
* declared type. Note that type is completely based on declared type,
* since nulls in Java have no type and thus runtime type cannot be
* determined.
*
* @since 2.0
*/
public JsonSerializer<Object> findNullKeySerializer(JavaType serializationType,
BeanProperty property)
throws JsonMappingException
{
return _nullKeySerializer;
}
Method called to get the serializer to use for serializing null
values for specified property.
Default implementation simply calls getDefaultNullValueSerializer()
; can be overridden to add custom null serialization for properties of certain type or name. This gives method full granularity to basically override null handling for any specific property or class of properties.
Since: 2.0
/**
* Method called to get the serializer to use for serializing null
* values for specified property.
*<p>
* Default implementation simply calls {@link #getDefaultNullValueSerializer()};
* can be overridden to add custom null serialization for properties
* of certain type or name. This gives method full granularity to basically
* override null handling for any specific property or class of properties.
*
* @since 2.0
*/
public JsonSerializer<Object> findNullValueSerializer(BeanProperty property)
throws JsonMappingException {
return _nullValueSerializer;
}
Method called to get the serializer to use if provider cannot determine an actual type-specific serializer to use; typically when none of SerializerFactory
instances are able to construct a serializer. Typically, returned serializer will throw an exception, although alternatively ToStringSerializer
could be returned as well.
Params: - unknownType – Type for which no serializer is found
/**
* Method called to get the serializer to use if provider
* cannot determine an actual type-specific serializer
* to use; typically when none of {@link SerializerFactory}
* instances are able to construct a serializer.
*<p>
* Typically, returned serializer will throw an exception,
* although alternatively {@link com.fasterxml.jackson.databind.ser.std.ToStringSerializer}
* could be returned as well.
*
* @param unknownType Type for which no serializer is found
*/
public JsonSerializer<Object> getUnknownTypeSerializer(Class<?> unknownType) {
// 23-Apr-2015, tatu: Only return shared instance if nominal type is Object.class
if (unknownType == Object.class) {
return _unknownTypeSerializer;
}
// otherwise construct explicit instance with property handled type
return new UnknownSerializer(unknownType);
}
Helper method called to see if given serializer is considered to be something returned by getUnknownTypeSerializer
, that is, something for which no regular serializer was found or constructed. Since: 2.5
/**
* Helper method called to see if given serializer is considered to be
* something returned by {@link #getUnknownTypeSerializer}, that is, something
* for which no regular serializer was found or constructed.
*
* @since 2.5
*/
public boolean isUnknownTypeSerializer(JsonSerializer<?> ser) {
if ((ser == _unknownTypeSerializer) || (ser == null)) {
return true;
}
// 23-Apr-2015, tatu: "empty" serializer is trickier; needs to consider
// error handling
if (isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
if (ser.getClass() == UnknownSerializer.class) {
return true;
}
}
return false;
}
/*
/**********************************************************
/* Methods for creating instances based on annotations
/**********************************************************
*/
Method that can be called to construct and configure serializer instance, either given a Class
to instantiate (with default constructor), or an uninitialized serializer instance. Either way, serialize will be properly resolved (via ResolvableSerializer
) and/or contextualized (via ContextualSerializer
) as necessary. Params: - annotated – Annotated entity that contained definition
- serDef – Serializer definition: either an instance or class
/**
* Method that can be called to construct and configure serializer instance,
* either given a {@link Class} to instantiate (with default constructor),
* or an uninitialized serializer instance.
* Either way, serialize will be properly resolved
* (via {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer}) and/or contextualized
* (via {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}) as necessary.
*
* @param annotated Annotated entity that contained definition
* @param serDef Serializer definition: either an instance or class
*/
public abstract JsonSerializer<Object> serializerInstance(Annotated annotated,
Object serDef)
throws JsonMappingException;
Method that can be called to construct and configure JsonInclude
filter instance, given a Class
to instantiate (with default constructor, by default). Params: - forProperty – (optional) If filter is created for a property, that property;
`null` if filter created via defaulting, global or per-type.
Since: 2.9
/**
* Method that can be called to construct and configure {@link JsonInclude}
* filter instance,
* given a {@link Class} to instantiate (with default constructor, by default).
*
* @param forProperty (optional) If filter is created for a property, that property;
* `null` if filter created via defaulting, global or per-type.
*
* @since 2.9
*/
public abstract Object includeFilterInstance(BeanPropertyDefinition forProperty,
Class<?> filterClass)
throws JsonMappingException;
Follow-up method that may be called after calling includeFilterInstance
, to check handling of `null` values by the filter. Since: 2.9
/**
* Follow-up method that may be called after calling {@link #includeFilterInstance},
* to check handling of `null` values by the filter.
*
* @since 2.9
*/
public abstract boolean includeFilterSuppressNulls(Object filter)
throws JsonMappingException;
/*
/**********************************************************
/* Support for contextualization
/**********************************************************
*/
Method called for primary property serializers (ones directly created to serialize values of a POJO property), to handle details of resolving ContextualSerializer
with given property context. Params: - property – Property for which the given primary serializer is used; never null.
Since: 2.3
/**
* Method called for primary property serializers (ones
* directly created to serialize values of a POJO property),
* to handle details of resolving
* {@link ContextualSerializer} with given property context.
*
* @param property Property for which the given primary serializer is used; never null.
*
* @since 2.3
*/
public JsonSerializer<?> handlePrimaryContextualization(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
if (ser != null) {
if (ser instanceof ContextualSerializer) {
ser = ((ContextualSerializer) ser).createContextual(this, property);
}
}
return ser;
}
Method called for secondary property serializers (ones NOT directly created to serialize values of a POJO property but instead created as a dependant serializer -- such as value serializers for structured types, or serializers for root values) to handle details of resolving ContextualDeserializer
with given property context. Given that these serializers 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. Params: - property – Property for which serializer is used, if any; null
when deserializing root values
Since: 2.3
/**
* Method called for secondary property serializers (ones
* NOT directly created to serialize values of a POJO property
* but instead created as a dependant serializer -- such as value serializers
* for structured types, or serializers for root values)
* to handle details of resolving
* {@link ContextualDeserializer} with given property context.
* Given that these serializers 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 property Property for which serializer is used, if any; null
* when deserializing root values
*
* @since 2.3
*/
public JsonSerializer<?> handleSecondaryContextualization(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
if (ser != null) {
if (ser instanceof ContextualSerializer) {
ser = ((ContextualSerializer) ser).createContextual(this, property);
}
}
return ser;
}
/*
/********************************************************
/* Convenience methods for serializing using default methods
/********************************************************
*/
Convenience method that will serialize given value (which can be null) using standard serializer locating functionality. It can be called for all values including field and Map values, but usually field values are best handled calling defaultSerializeField
instead. /**
* Convenience method that will serialize given value (which can be
* null) using standard serializer locating functionality. It can
* be called for all values including field and Map values, but usually
* field values are best handled calling
* {@link #defaultSerializeField} instead.
*/
public final void defaultSerializeValue(Object value, JsonGenerator gen) throws IOException
{
if (value == null) {
if (_stdNullValueSerializer) { // minor perf optimization
gen.writeNull();
} else {
_nullValueSerializer.serialize(null, gen, this);
}
} else {
Class<?> cls = value.getClass();
findTypedValueSerializer(cls, true, null).serialize(value, gen, this);
}
}
Convenience method that will serialize given field with specified
value. Value may be null. Serializer is done using the usual
null) using standard serializer locating functionality.
/**
* Convenience method that will serialize given field with specified
* value. Value may be null. Serializer is done using the usual
* null) using standard serializer locating functionality.
*/
public final void defaultSerializeField(String fieldName, Object value, JsonGenerator gen)
throws IOException
{
gen.writeFieldName(fieldName);
if (value == null) {
/* Note: can't easily check for suppression at this point
* any more; caller must check it.
*/
if (_stdNullValueSerializer) { // minor perf optimization
gen.writeNull();
} else {
_nullValueSerializer.serialize(null, gen, this);
}
} else {
Class<?> cls = value.getClass();
findTypedValueSerializer(cls, true, null).serialize(value, gen, this);
}
}
Method that will handle serialization of Date(-like) values, using SerializationConfig
settings to determine expected serialization behavior. Note: date here means "full" date, that is, date AND time, as per Java convention (and not date-only values like in SQL) /**
* Method that will handle serialization of Date(-like) values, using
* {@link SerializationConfig} settings to determine expected serialization
* behavior.
* Note: date here means "full" date, that is, date AND time, as per
* Java convention (and not date-only values like in SQL)
*/
public final void defaultSerializeDateValue(long timestamp, JsonGenerator gen)
throws IOException
{
if (isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) {
gen.writeNumber(timestamp);
} else {
gen.writeString(_dateFormat().format(new Date(timestamp)));
}
}
Method that will handle serialization of Date(-like) values, using SerializationConfig
settings to determine expected serialization behavior. Note: date here means "full" date, that is, date AND time, as per Java convention (and not date-only values like in SQL) /**
* Method that will handle serialization of Date(-like) values, using
* {@link SerializationConfig} settings to determine expected serialization
* behavior.
* Note: date here means "full" date, that is, date AND time, as per
* Java convention (and not date-only values like in SQL)
*/
public final void defaultSerializeDateValue(Date date, JsonGenerator gen) throws IOException
{
if (isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) {
gen.writeNumber(date.getTime());
} else {
gen.writeString(_dateFormat().format(date));
}
}
Method that will handle serialization of Dates used as Map
keys, based on SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS
value (and if using textual representation, configured date format) /**
* Method that will handle serialization of Dates used as {@link java.util.Map} keys,
* based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS}
* value (and if using textual representation, configured date format)
*/
public void defaultSerializeDateKey(long timestamp, JsonGenerator gen) throws IOException
{
if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) {
gen.writeFieldName(String.valueOf(timestamp));
} else {
gen.writeFieldName(_dateFormat().format(new Date(timestamp)));
}
}
Method that will handle serialization of Dates used as Map
keys, based on SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS
value (and if using textual representation, configured date format) /**
* Method that will handle serialization of Dates used as {@link java.util.Map} keys,
* based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS}
* value (and if using textual representation, configured date format)
*/
public void defaultSerializeDateKey(Date date, JsonGenerator gen) throws IOException
{
if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) {
gen.writeFieldName(String.valueOf(date.getTime()));
} else {
gen.writeFieldName(_dateFormat().format(date));
}
}
public final void defaultSerializeNull(JsonGenerator gen) throws IOException
{
if (_stdNullValueSerializer) { // minor perf optimization
gen.writeNull();
} else {
_nullValueSerializer.serialize(null, gen, this);
}
}
/*
/********************************************************
/* Error reporting
/********************************************************
*/
Helper method called to indicate problem; default behavior is to construct and throw a JsonMappingException
, but in future may collect more than one and only throw after certain number, or at the end of serialization. Since: 2.8
/**
* Helper method called to indicate problem; default behavior is to construct and
* throw a {@link JsonMappingException}, but in future may collect more than one
* and only throw after certain number, or at the end of serialization.
*
* @since 2.8
*/
public void reportMappingProblem(String message, Object... args) throws JsonMappingException {
throw mappingException(message, args);
}
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 JsonMappingException
. Since: 2.9
/**
* 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> T reportBadTypeDefinition(BeanDescription bean,
String msg, Object... msgArgs) throws JsonMappingException {
String beanDesc = "N/A";
if (bean != null) {
beanDesc = ClassUtil.nameOf(bean.getBeanClass());
}
msg = String.format("Invalid type definition for type %s: %s",
beanDesc, _format(msg, msgArgs));
throw InvalidDefinitionException.from(getGenerator(), 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 JsonMappingException
. Since: 2.9
/**
* 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> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
String message, Object... msgArgs) throws JsonMappingException {
message = _format(message, msgArgs);
String propName = "N/A";
if (prop != null) {
propName = _quotedString(prop.getName());
}
String beanDesc = "N/A";
if (bean != null) {
beanDesc = ClassUtil.nameOf(bean.getBeanClass());
}
message = String.format("Invalid definition for property %s (of type %s): %s",
propName, beanDesc, message);
throw InvalidDefinitionException.from(getGenerator(), message, bean, prop);
}
@Override
public <T> T reportBadDefinition(JavaType type, String msg) throws JsonMappingException {
throw InvalidDefinitionException.from(getGenerator(), msg, type);
}
Since: 2.9
/**
* @since 2.9
*/
public <T> T reportBadDefinition(JavaType type, String msg, Throwable cause)
throws JsonMappingException {
InvalidDefinitionException e = InvalidDefinitionException.from(getGenerator(), msg, type);
e.initCause(cause);
throw e;
}
Since: 2.9
/**
* @since 2.9
*/
public <T> T reportBadDefinition(Class<?> raw, String msg, Throwable cause)
throws JsonMappingException {
InvalidDefinitionException e = InvalidDefinitionException.from(getGenerator(), msg, constructType(raw));
e.initCause(cause);
throw e;
}
Helper method called to indicate problem; default behavior is to construct and throw a JsonMappingException
, but in future may collect more than one and only throw after certain number, or at the end of serialization. Since: 2.8
/**
* Helper method called to indicate problem; default behavior is to construct and
* throw a {@link JsonMappingException}, but in future may collect more than one
* and only throw after certain number, or at the end of serialization.
*
* @since 2.8
*/
public void reportMappingProblem(Throwable t, String message, Object... msgArgs) throws JsonMappingException {
message = _format(message, msgArgs);
throw JsonMappingException.from(getGenerator(), message, t);
}
@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(null, _colonConcat(msg, extraDesc), baseType, typeId);
}
/*
/********************************************************
/* Error reporting, deprecated methods
/********************************************************
*/
Factory method for constructing a JsonMappingException
; usually only indirectly used by calling reportMappingProblem(String, Object...)
. Since: 2.6 Deprecated: Since 2.9
/**
* Factory method for constructing a {@link JsonMappingException};
* usually only indirectly used by calling
* {@link #reportMappingProblem(String, Object...)}.
*
* @since 2.6
*
* @deprecated Since 2.9
*/
@Deprecated // since 2.9
public JsonMappingException mappingException(String message, Object... msgArgs) {
return JsonMappingException.from(getGenerator(), _format(message, msgArgs));
}
Factory method for constructing a JsonMappingException
; usually only indirectly used by calling reportMappingProblem(Throwable, String, Object...)
Since: 2.8 Deprecated: Since 2.9
/**
* Factory method for constructing a {@link JsonMappingException};
* usually only indirectly used by calling
* {@link #reportMappingProblem(Throwable, String, Object...)}
*
* @since 2.8
*
* @deprecated Since 2.9
*/
@Deprecated // since 2.9
protected JsonMappingException mappingException(Throwable t, String message, Object... msgArgs) {
return JsonMappingException.from(getGenerator(), _format(message, msgArgs), t);
}
/*
/********************************************************
/* Helper methods
/********************************************************
*/
protected void _reportIncompatibleRootType(Object value, JavaType rootType) throws IOException
{
// One special case: allow primitive/wrapper type coercion
if (rootType.isPrimitive()) {
Class<?> wrapperType = ClassUtil.wrapperType(rootType.getRawClass());
// If it's just difference between wrapper, primitive, let it slide
if (wrapperType.isAssignableFrom(value.getClass())) {
return;
}
}
reportBadDefinition(rootType, String.format(
"Incompatible types: declared root type (%s) vs %s",
rootType, ClassUtil.classNameOf(value)));
}
Method that will try to find a serializer, either from cache
or by constructing one; but will not return an "unknown" serializer
if this cannot be done but rather returns null.
Returns: Serializer if one can be found, null if not.
/**
* Method that will try to find a serializer, either from cache
* or by constructing one; but will not return an "unknown" serializer
* if this cannot be done but rather returns null.
*
* @return Serializer if one can be found, null if not.
*/
protected JsonSerializer<Object> _findExplicitUntypedSerializer(Class<?> runtimeType)
throws JsonMappingException
{
// Fast lookup from local lookup thingy works?
JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(runtimeType);
if (ser == null) {
// If not, maybe shared map already has it?
ser = _serializerCache.untypedValueSerializer(runtimeType);
if (ser == null) {
ser = _createAndCacheUntypedSerializer(runtimeType);
}
}
/* 18-Sep-2014, tatu: This is unfortunate patch over related change
* that pushes creation of "unknown type" serializer deeper down
* in BeanSerializerFactory; as a result, we need to "undo" creation
* here.
*/
if (isUnknownTypeSerializer(ser)) {
return null;
}
return ser;
}
/*
/**********************************************************
/* Low-level methods for actually constructing and initializing
/* serializers
/**********************************************************
*/
Method that will try to construct a value serializer; and if
one is successfully created, cache it for reuse.
/**
* Method that will try to construct a value serializer; and if
* one is successfully created, cache it for reuse.
*/
protected JsonSerializer<Object> _createAndCacheUntypedSerializer(Class<?> rawType)
throws JsonMappingException
{
JavaType fullType = _config.constructType(rawType);
JsonSerializer<Object> ser;
try {
ser = _createUntypedSerializer(fullType);
} catch (IllegalArgumentException iae) {
// We better only expose checked exceptions, since those
// are what caller is expected to handle
ser = null; // doesn't matter but compiler whines otherwise
reportMappingProblem(iae, ClassUtil.exceptionMessage(iae));
}
if (ser != null) {
// 21-Dec-2015, tatu: Best to cache for both raw and full-type key
_serializerCache.addAndResolveNonTypedSerializer(rawType, fullType, ser, this);
}
return ser;
}
protected JsonSerializer<Object> _createAndCacheUntypedSerializer(JavaType type)
throws JsonMappingException
{
JsonSerializer<Object> ser;
try {
ser = _createUntypedSerializer(type);
} catch (IllegalArgumentException iae) {
// We better only expose checked exceptions, since those
// are what caller is expected to handle
ser = null;
reportMappingProblem(iae, ClassUtil.exceptionMessage(iae));
}
if (ser != null) {
// 21-Dec-2015, tatu: Should we also cache using raw key?
_serializerCache.addAndResolveNonTypedSerializer(type, ser, this);
}
return ser;
}
Since: 2.1
/**
* @since 2.1
*/
protected JsonSerializer<Object> _createUntypedSerializer(JavaType type)
throws JsonMappingException
{
/* 27-Mar-2015, tatu: Wish I knew exactly why/what, but [databind#738]
* can be prevented by synchronizing on cache (not on 'this', however,
* since there's one instance per serialization).
* Perhaps not-yet-resolved instance might be exposed too early to callers.
*/
// 13-Apr-2018, tatu: Problem does NOT occur any more with late 2.8.x and 2.9.x
// versions, likely due to concurrency fixes for `AnnotatedClass` introspection.
// This sync block could probably be removed; but to minimize any risk of
// regression sync block will only be removed from 3.0.
// 23-Oct-2019, tatu: Due to continuation of 2.x line, removed from 2.11
// synchronized (_serializerCache) {
return (JsonSerializer<Object>)_serializerFactory.createSerializer(this, type);
// }
}
Helper method called to resolve and contextualize given
serializer, if and as necessary.
/**
* Helper method called to resolve and contextualize given
* serializer, if and as necessary.
*/
@SuppressWarnings("unchecked")
protected JsonSerializer<Object> _handleContextualResolvable(JsonSerializer<?> ser,
BeanProperty property)
throws JsonMappingException
{
if (ser instanceof ResolvableSerializer) {
((ResolvableSerializer) ser).resolve(this);
}
return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property);
}
@SuppressWarnings("unchecked")
protected JsonSerializer<Object> _handleResolvable(JsonSerializer<?> ser)
throws JsonMappingException
{
if (ser instanceof ResolvableSerializer) {
((ResolvableSerializer) ser).resolve(this);
}
return (JsonSerializer<Object>) ser;
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected final DateFormat _dateFormat()
{
if (_dateFormat != null) {
return _dateFormat;
}
/* At this point, all timezone configuration should have occurred, with respect
* to default dateformat configuration. But we still better clone
* an instance as formatters are stateful, not thread-safe.
*/
DateFormat df = _config.getDateFormat();
_dateFormat = df = (DateFormat) df.clone();
// [databind#939]: 26-Sep-2015, tatu: With 2.6, formatter has been (pre)configured
// with TimeZone, so we should NOT try overriding it unlike with earlier versions
/*
TimeZone tz = getTimeZone();
if (tz != df.getTimeZone()) {
df.setTimeZone(tz);
}
*/
return df;
}
}