package org.codehaus.jackson.map;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Date;
import org.codehaus.jackson.*;
import org.codehaus.jackson.map.ser.FilterProvider;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.schema.JsonSchema;
import org.codehaus.jackson.type.JavaType;
/**
* Abstract class that defines API used by {@link ObjectMapper} and
* {@link JsonSerializer}s to obtain serializers capable of serializing
* instances of specific types.
*
* Note about usage: for {@link JsonSerializer} instances, only accessors
* for locating other (sub-)serializers are to be used. {@link ObjectMapper},
* on the other hand, is to initialize recursive serialization process by
* calling {@link #serializeValue}.
*/
public abstract class SerializerProvider
{
protected final static JavaType TYPE_OBJECT = TypeFactory.defaultInstance().uncheckedSimpleType(Object.class);
/**
* Serialization configuration to use for serialization processing.
*/
protected final SerializationConfig _config;
/**
* View used for currently active serialization
*/
protected final Class> _serializationView;
protected SerializerProvider(SerializationConfig config)
{
_config = config;
_serializationView = (config == null) ? null : _config.getSerializationView();
}
/*
/**********************************************************
/* 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)
*
* @since 1.8
*/
public abstract void setNullKeySerializer(JsonSerializer nks);
/**
* 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)
*
* @since 1.8
*/
public abstract void setNullValueSerializer(JsonSerializer 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.
*
* @since 1.8
*/
public abstract void setDefaultKeySerializer(JsonSerializer ks);
/*
/**********************************************************
/* Methods that ObjectMapper will call
/**********************************************************
*/
/**
* The method to be called by {@link ObjectMapper} to
* execute recursive serialization, using serializers that
* this provider has access to.
*
* @param jsf Underlying factory object used for creating serializers
* as needed
*/
public abstract void serializeValue(SerializationConfig cfg, JsonGenerator jgen,
Object value, SerializerFactory jsf)
throws IOException, JsonGenerationException;
/**
* The method to be called by {@link ObjectMapper} to
* execute recursive serialization, using serializers that
* this provider has access to; and using specified root type
* for locating first-level serializer.
*
* @param rootType Type to use for locating serializer to use, instead of actual
* runtime type. Must be actual type, or one of its super types
*
* @since 1.5
*/
public abstract void serializeValue(SerializationConfig cfg, JsonGenerator jgen,
Object value, JavaType rootType, SerializerFactory jsf)
throws IOException, JsonGenerationException;
/**
* Generate Json-schema for
* given type.
*
* @param type The type for which to generate schema
*/
public abstract JsonSchema generateJsonSchema(Class> type, SerializationConfig config, SerializerFactory jsf)
throws JsonMappingException;
/**
* Method that can be called to see if this serializer provider
* can find a serializer for an instance of given class.
*
* Note that no Exceptions are thrown, including unchecked ones:
* implementations are to swallow exceptions if necessary.
*/
public abstract boolean hasSerializerFor(SerializationConfig cfg,
Class> cls, SerializerFactory jsf);
/*
/**********************************************************
/* Access to configuration
/**********************************************************
*/
/**
* Method for accessing configuration for the serialization processing.
*/
public final SerializationConfig getConfig() { return _config; }
/**
* Convenience method for checking whether specified serialization
* feature is enabled or not.
* Shortcut for:
*
* getConfig().isEnabled(feature);
*
*/
public final boolean isEnabled(SerializationConfig.Feature feature) {
return _config.isEnabled(feature);
}
/**
* Convenience method for accessing serialization view in use (if any); equivalent to:
*
* getConfig().getSerializationView();
*
*
* @since 1.4
*/
public final Class> getSerializationView() { return _serializationView; }
/**
* Convenience method for accessing provider to find serialization filters used,
* equivalent to calling:
*
* getConfig().getFilterProvider();
*
*
* @since 1.4
*/
public final FilterProvider getFilterProvider() {
return _config.getFilterProvider();
}
/**
* @since 1.8
*/
public JavaType constructType(Type type) {
return _config.getTypeFactory().constructType(type);
}
/**
* @since 1.9.1
*/
public JavaType constructSpecializedType(JavaType baseType, Class> subclass) {
return _config.constructSpecializedType(baseType, subclass);
}
/*
/**********************************************************
/* 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 starting with version 1.5, serializers should also be type-aware
* if they handle polymorphic types. That means that it may be necessary
* to also use a {@link TypeSerializer} based on declared (static) type
* being serializer (whereas actual data may be serialized using dynamic
* type)
*
* @throws JsonMappingException if there are fatal problems with
* accessing suitable serializer; including that of not
* finding any serializer
*/
public abstract JsonSerializer findValueSerializer(Class> runtimeType,
BeanProperty property)
throws JsonMappingException;
/**
* Similar to {@link #findValueSerializer(Class)}, but takes full generics-aware
* type instead of raw class.
*
* @since 1.5
*/
public abstract JsonSerializer findValueSerializer(JavaType serializationType,
BeanProperty property)
throws JsonMappingException;
/**
* 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
*
* @since 1.5
*/
public abstract JsonSerializer findTypedValueSerializer(Class> valueType,
boolean cache, BeanProperty property)
throws JsonMappingException;
/**
* 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
*
* @since 1.5
*/
public abstract JsonSerializer findTypedValueSerializer(JavaType valueType,
boolean cache, BeanProperty property)
throws JsonMappingException;
/**
* 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.
*
* Note that the serializer itself can be called with instances
* of any Java object, but not nulls.
*
* @since 1.8
*/
public abstract JsonSerializer findKeySerializer(JavaType keyType,
BeanProperty property)
throws JsonMappingException;
/*
/**********************************************************
/* Deprecated serializer locating functionality
/**********************************************************
*/
/**
* Deprecated version of accessor method that was used before version 1.7.
* Implemented as final to ensure that existing code does not accidentally
* try to redefine it (given that it is not called by core mapper code)
*
* @deprecated As of version 1.7, use version that exposes property object
* instead of just its type (needed for contextual serializers)
*/
@Deprecated
public final JsonSerializer findValueSerializer(Class> runtimeType)
throws JsonMappingException
{
return findValueSerializer(runtimeType, null);
}
/**
* Deprecated version of accessor method that was used before version 1.7.
* Implemented as final to ensure that existing code does not accidentally
* try to redefine it (given that it is not called by core mapper code)
*
* @deprecated As of version 1.7, use version that exposes property object
* instead of just its type (needed for contextual serializers)
*/
@Deprecated
public final JsonSerializer findValueSerializer(JavaType serializationType)
throws JsonMappingException
{
return findValueSerializer(serializationType, null);
}
/**
* Deprecated version of accessor method that was used before version 1.7.
* Implemented as final to ensure that existing code does not accidentally
* try to redefine it (given that it is not called by core mapper code)
*
* @deprecated As of version 1.7, use version that exposes property object
* instead of just its type (needed for contextual serializers)
*/
@Deprecated
public final JsonSerializer findTypedValueSerializer(Class> valueType,
boolean cache)
throws JsonMappingException
{
return findTypedValueSerializer(valueType, cache, null);
}
/**
* Deprecated version of accessor method that was used before version 1.7.
* Implemented as final to ensure that existing code does not accidentally
* try to redefine it (given that it is not called by core mapper code)
*
* @deprecated As of version 1.7, use version that exposes property object
* instead of just its type (needed for contextual serializers)
*/
@Deprecated
public final JsonSerializer findTypedValueSerializer(JavaType valueType,
boolean cache)
throws JsonMappingException
{
return findTypedValueSerializer(valueType, cache, null);
}
/**
* Deprecated version of accessor method that was used before version 1.7.
* Implemented as final to ensure that existing code does not accidentally
* try to redefine it (given that it is not called by core mapper code)
*
* @deprecated As of version 1.7, use version that exposes property object
* instead of just its type (needed for contextual serializers)
*/
@Deprecated
public final JsonSerializer getKeySerializer()
throws JsonMappingException
{
return findKeySerializer(TYPE_OBJECT, null);
}
/**
* Deprecated version of accessor method that was used before version 1.8;
* renamed as {@link #findKeySerializer}, since process is now
* more complicated than simple lookup.
*
* @deprecated As of version 1.8
*/
@Deprecated
public final JsonSerializer getKeySerializer(JavaType valueType, BeanProperty property)
throws JsonMappingException
{
return findKeySerializer(valueType, property);
}
/*
/********************************************************
/* Accessors for specialized serializers
/********************************************************
*/
/**
* 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.
*
* Typically, returned serializer
* will either throw an exception, or use an empty String; but
* other behaviors are possible.
*/
public abstract JsonSerializer getNullKeySerializer();
/**
* Method called to get the serializer to use for serializing
* values (root level, Array members or List field values)
* that are nulls. Specific accessor is needed because nulls
* in Java do not contain type information.
*
* Typically returned serializer just writes out Json literal
* null value.
*/
public abstract JsonSerializer getNullValueSerializer();
/**
* Method called to get the serializer to use if provider
* can not determine an actual type-specific serializer
* to use; typically when none of {@link SerializerFactory}
* instances are able to construct a serializer.
*
* Typically, returned serializer will throw an exception,
* although alternatively {@link org.codehaus.jackson.map.ser.ToStringSerializer} could
* be returned as well.
*
* @param unknownType Type for which no serializer is found
*/
public abstract JsonSerializer getUnknownTypeSerializer(Class> unknownType);
/*
/********************************************************
/* Convenience 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
* {@link #defaultSerializeField} instead.
*/
public final void defaultSerializeValue(Object value, JsonGenerator jgen)
throws IOException, JsonProcessingException
{
if (value == null) {
getNullValueSerializer().serialize(null, jgen, this);
} else {
Class> cls = value.getClass();
findTypedValueSerializer(cls, true, null).serialize(value, jgen, 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.
*/
public final void defaultSerializeField(String fieldName, Object value, JsonGenerator jgen)
throws IOException, JsonProcessingException
{
jgen.writeFieldName(fieldName);
if (value == null) {
/* Note: can't easily check for suppression at this point
* any more; caller must check it.
*/
getNullValueSerializer().serialize(null, jgen, this);
} else {
Class> cls = value.getClass();
findTypedValueSerializer(cls, true, null).serialize(value, jgen, this);
}
}
/**
* 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 abstract void defaultSerializeDateValue(long timestamp, JsonGenerator jgen)
throws IOException, JsonProcessingException;
/**
* 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 abstract void defaultSerializeDateValue(Date date, JsonGenerator jgen)
throws IOException, JsonProcessingException;
/**
* Method that will handle serialization of Dates used as {@link java.util.Map} keys,
* based on {@link SerializationConfig.Feature#WRITE_DATE_KEYS_AS_TIMESTAMPS}
* value (and if using textual representation, configured date format)
*
* @since 1.9
*/
public abstract void defaultSerializeDateKey(long timestamp, JsonGenerator jgen)
throws IOException, JsonProcessingException;
/**
* Method that will handle serialization of Dates used as {@link java.util.Map} keys,
* based on {@link SerializationConfig.Feature#WRITE_DATE_KEYS_AS_TIMESTAMPS}
* value (and if using textual representation, configured date format)
*
* @since 1.9
*/
public abstract void defaultSerializeDateKey(Date date, JsonGenerator jgen)
throws IOException, JsonProcessingException;
/**
* @since 1.7
*/
public final void defaultSerializeNull(JsonGenerator jgen)
throws IOException, JsonProcessingException
{
getNullValueSerializer().serialize(null, jgen, this);
}
/*
/********************************************************
/* Access to caching details
/********************************************************
*/
/**
* Method that can be used to determine how many serializers this
* provider is caching currently
* (if it does caching: default implementation does)
* Exact count depends on what kind of serializers get cached;
* default implementation caches all serializers, including ones that
* are eagerly constructed (for optimal access speed)
*
* The main use case for this method is to allow conditional flushing of
* serializer cache, if certain number of entries is reached.
*
* @since 1.4
*/
public abstract int cachedSerializersCount();
/**
* Method that will drop all serializers currently cached by this provider.
* This can be used to remove memory usage (in case some serializers are
* only used once or so), or to force re-construction of serializers after
* configuration changes for mapper than owns the provider.
*
* @since 1.4
*/
public abstract void flushCachedSerializers();
}