package com.fasterxml.jackson.databind; import java.text.DateFormat; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.databind.cfg.BaseSettings; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfigBase; import com.fasterxml.jackson.databind.introspect.ClassIntrospector; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.SerializerFactory; import com.fasterxml.jackson.databind.type.ClassKey; import com.fasterxml.jackson.databind.type.TypeFactory; /** * Object that contains baseline configuration for serialization * process. An instance is owned by {@link ObjectMapper}, which * passes an immutable instance for serialization process to * {@link SerializerProvider} and {@link SerializerFactory} * (either directly, or through {@link ObjectWriter}. *<p> * 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. * Note also that unlike with Jackson 1, these instances can not be * assigned to {@link ObjectMapper}; in fact, application code should * rarely interact directly with these instance (unlike core Jackson code) */ public final class SerializationConfig extends MapperConfigBase<SerializationFeature, SerializationConfig> implements java.io.Serializable // since 2.1 { // for 2.1.0: private static final long serialVersionUID = 8849092838541724233L; /** * Set of features enabled; actual type (kind of features) * depends on sub-classes. */ protected final int _serFeatures; /** * Which Bean/Map properties are to be included in serialization? * Default settings is to include all regardless of value; can be * changed to only include non-null properties, or properties * with non-default values. */ protected JsonInclude.Include _serializationInclusion = null; /** * Object used for resolving filter ids to filter instances. * Non-null if explicitly defined; null by default. */ protected final FilterProvider _filterProvider; /* /********************************************************** /* Life-cycle, constructors /********************************************************** */ /** * Constructor used by ObjectMapper to create default configuration object instance. */ public SerializationConfig(BaseSettings base, SubtypeResolver str, Map<ClassKey,Class<?>> mixins) { super(base, str, mixins); _serFeatures = collectFeatureDefaults(SerializationFeature.class); _filterProvider = null; } private SerializationConfig(SerializationConfig src, SubtypeResolver str) { super(src, str); _serFeatures = src._serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = src._filterProvider; } private SerializationConfig(SerializationConfig src, int mapperFeatures, int serFeatures) { super(src, mapperFeatures); _serFeatures = serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = src._filterProvider; } private SerializationConfig(SerializationConfig src, BaseSettings base) { super(src, base); _serFeatures = src._serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = src._filterProvider; } private SerializationConfig(SerializationConfig src, FilterProvider filters) { super(src); _serFeatures = src._serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = filters; } private SerializationConfig(SerializationConfig src, Class<?> view) { super(src, view); _serFeatures = src._serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = src._filterProvider; } private SerializationConfig(SerializationConfig src, JsonInclude.Include incl) { super(src); _serFeatures = src._serFeatures; _serializationInclusion = incl; _filterProvider = src._filterProvider; } private SerializationConfig(SerializationConfig src, String rootName) { super(src, rootName); _serFeatures = src._serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = src._filterProvider; } /** * @since 2.1 */ protected SerializationConfig(SerializationConfig src, Map<ClassKey,Class<?>> mixins) { super(src, mixins); _serFeatures = src._serFeatures; _serializationInclusion = src._serializationInclusion; _filterProvider = src._filterProvider; } /* /********************************************************** /* Life-cycle, factory methods from MapperConfig /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ @Override public SerializationConfig with(MapperFeature... features) { int newMapperFlags = _mapperFeatures; for (MapperFeature f : features) { newMapperFlags |= f.getMask(); } return (newMapperFlags == _mapperFeatures) ? this : new SerializationConfig(this, newMapperFlags, _serFeatures); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ @Override public SerializationConfig without(MapperFeature... features) { int newMapperFlags = _mapperFeatures; for (MapperFeature f : features) { newMapperFlags &= ~f.getMask(); } return (newMapperFlags == _mapperFeatures) ? this : new SerializationConfig(this, newMapperFlags, _serFeatures); } @Override public SerializationConfig with(AnnotationIntrospector ai) { return _withBase(_base.withAnnotationIntrospector(ai)); } @Override public SerializationConfig withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { return _withBase(_base.withAppendedAnnotationIntrospector(ai)); } @Override public SerializationConfig withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { return _withBase(_base.withInsertedAnnotationIntrospector(ai)); } @Override public SerializationConfig with(ClassIntrospector ci) { return _withBase(_base.withClassIntrospector(ci)); } /** * In addition to constructing instance with specified date format, * will enable or disable <code>SerializationFeature.WRITE_DATES_AS_TIMESTAMPS</code> * (enable if format set as null; disable if non-null) */ @Override public SerializationConfig with(DateFormat df) { SerializationConfig cfg = new SerializationConfig(this, _base.withDateFormat(df)); // Also need to toggle this feature based on existence of date format: if (df == null) { cfg = cfg.with(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } else { cfg = cfg.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } return cfg; } @Override public SerializationConfig with(HandlerInstantiator hi) { return _withBase(_base.withHandlerInstantiator(hi)); } @Override public SerializationConfig with(PropertyNamingStrategy pns) { return _withBase(_base.withPropertyNamingStrategy(pns)); } @Override public SerializationConfig withRootName(String rootName) { if (rootName == null) { if (_rootName == null) { return this; } } else if (rootName.equals(_rootName)) { return this; } return new SerializationConfig(this, rootName); } @Override public SerializationConfig with(SubtypeResolver str) { return (str == _subtypeResolver)? this : new SerializationConfig(this, str); } @Override public SerializationConfig with(TypeFactory tf) { return _withBase(_base.withTypeFactory(tf)); } @Override public SerializationConfig with(TypeResolverBuilder<?> trb) { return _withBase(_base.withTypeResolverBuilder(trb)); } @Override public SerializationConfig withView(Class<?> view) { return (_view == view) ? this : new SerializationConfig(this, view); } @Override public SerializationConfig with(VisibilityChecker<?> vc) { return _withBase(_base.withVisibilityChecker(vc)); } @Override public SerializationConfig withVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) { return _withBase(_base.withVisibility(forMethod, visibility)); } @Override public SerializationConfig with(Locale l) { return _withBase(_base.with(l)); } @Override public SerializationConfig with(TimeZone tz) { return _withBase(_base.with(tz)); } @Override public SerializationConfig with(Base64Variant base64) { return _withBase(_base.with(base64)); } private final SerializationConfig _withBase(BaseSettings newBase) { return (_base == newBase) ? this : new SerializationConfig(this, newBase); } /* /********************************************************** /* Life-cycle, SerializationConfig specific factory methods /********************************************************** */ /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature enabled. */ public SerializationConfig with(SerializationFeature feature) { int newSerFeatures = _serFeatures | feature.getMask(); return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public SerializationConfig with(SerializationFeature first, SerializationFeature... features) { int newSerFeatures = _serFeatures | first.getMask(); for (SerializationFeature f : features) { newSerFeatures |= f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features enabled. */ public SerializationConfig withFeatures(SerializationFeature... features) { int newSerFeatures = _serFeatures; for (SerializationFeature f : features) { newSerFeatures |= f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified feature disabled. */ public SerializationConfig without(SerializationFeature feature) { int newSerFeatures = _serFeatures & ~feature.getMask(); return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ public SerializationConfig without(SerializationFeature first, SerializationFeature... features) { int newSerFeatures = _serFeatures & ~first.getMask(); for (SerializationFeature f : features) { newSerFeatures &= ~f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures); } /** * Fluent factory method that will construct and return a new configuration * object instance with specified features disabled. */ public SerializationConfig withoutFeatures(SerializationFeature... features) { int newSerFeatures = _serFeatures; for (SerializationFeature f : features) { newSerFeatures &= ~f.getMask(); } return (newSerFeatures == _serFeatures) ? this : new SerializationConfig(this, _mapperFeatures, newSerFeatures); } public SerializationConfig withFilters(FilterProvider filterProvider) { return (filterProvider == _filterProvider) ? this : new SerializationConfig(this, filterProvider); } public SerializationConfig withSerializationInclusion(JsonInclude.Include incl) { return (_serializationInclusion == incl) ? this: new SerializationConfig(this, incl); } /* /********************************************************** /* MapperConfig implementation/overrides /********************************************************** */ @Override public boolean useRootWrapping() { if (_rootName != null) { // empty String disables wrapping; non-empty enables return (_rootName.length() > 0); } return isEnabled(SerializationFeature.WRAP_ROOT_VALUE); } @Override public AnnotationIntrospector getAnnotationIntrospector() { /* 29-Jul-2009, tatu: it's now possible to disable use of * annotations; can be done using "no-op" introspector */ if (isEnabled(MapperFeature.USE_ANNOTATIONS)) { return super.getAnnotationIntrospector(); } return AnnotationIntrospector.nopInstance(); } /** * Accessor for getting bean description that only contains class * annotations: useful if no getter/setter/creator information is needed. */ @Override public BeanDescription introspectClassAnnotations(JavaType type) { return getClassIntrospector().forClassAnnotations(this, type, this); } /** * Accessor for getting bean description that only contains immediate class * annotations: ones from the class, and its direct mix-in, if any, but * not from super types. */ @Override public BeanDescription introspectDirectClassAnnotations(JavaType type) { return getClassIntrospector().forDirectClassAnnotations(this, type, this); } @Override public VisibilityChecker<?> getDefaultVisibilityChecker() { VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker(); if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) { vchecker = vchecker.withGetterVisibility(Visibility.NONE); } // then global overrides (disabling) if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) { vchecker = vchecker.withIsGetterVisibility(Visibility.NONE); } if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) { vchecker = vchecker.withFieldVisibility(Visibility.NONE); } return vchecker; } /* /********************************************************** /* Configuration: other /********************************************************** */ public final boolean isEnabled(SerializationFeature f) { return (_serFeatures & f.getMask()) != 0; } public final int getSerializationFeatures() { return _serFeatures; } public JsonInclude.Include getSerializationInclusion() { if (_serializationInclusion != null) { return _serializationInclusion; } return JsonInclude.Include.ALWAYS; } /** * Method for getting provider used for locating filters given * id (which is usually provided with filter annotations). * Will be null if no provided was set for {@link ObjectWriter} * (or if serialization directly called from {@link ObjectMapper}) */ public FilterProvider getFilterProvider() { return _filterProvider; } /* /********************************************************** /* Introspection methods /********************************************************** */ /** * Method that will introspect full bean properties for the purpose * of building a bean serializer */ @SuppressWarnings("unchecked") public <T extends BeanDescription> T introspect(JavaType type) { return (T) getClassIntrospector().forSerialization(this, type, this); } /* /********************************************************** /* Debug support /********************************************************** */ @Override public String toString() { return "[SerializationConfig: flags=0x"+Integer.toHexString(_serFeatures)+"]"; } }