/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.http.converter.json;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;

A FactoryBean for creating a Jackson 2.x ObjectMapper (default) or XmlMapper (createXmlMapper property set to true) with setters to enable or disable Jackson features from within XML configuration.

It customizes Jackson defaults properties with the following ones:

  • DEFAULT_VIEW_INCLUSION.DEFAULT_VIEW_INCLUSION is disabled
  • FAIL_ON_UNKNOWN_PROPERTIES.FAIL_ON_UNKNOWN_PROPERTIES is disabled

Example usage with MappingJackson2HttpMessageConverter:

<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  <property name="objectMapper">
    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
      p:autoDetectFields="false"
      p:autoDetectGettersSetters="false"
      p:annotationIntrospector-ref="jaxbAnnotationIntrospector" />
  </property>
</bean>

Example usage with MappingJackson2JsonView:

<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
  <property name="objectMapper">
    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
      p:failOnEmptyBeans="false"
      p:indentOutput="true">
      <property name="serializers">
        <array>
          <bean class="org.mycompany.MyCustomSerializer" />
        </array>
      </property>
    </bean>
  </property>
</bean>

In case there are no specific setters provided (for some rarely used options), you can still use the more general methods setFeaturesToEnable and setFeaturesToDisable.

<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
  <property name="featuresToEnable">
    <array>
      <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRAP_ROOT_VALUE"/>
      <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.CLOSE_CLOSEABLE"/>
    </array>
  </property>
  <property name="featuresToDisable">
    <array>
      <util:constant static-field="com.fasterxml.jackson.databind.MapperFeature.USE_ANNOTATIONS"/>
    </array>
  </property>
</bean>

It also automatically registers the following well-known modules if they are detected on the classpath:

In case you want to configure Jackson's ObjectMapper with a custom Module, you can register one or more such Modules by class name via setModulesToInstall:

<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
  <property name="modulesToInstall" value="myapp.jackson.MySampleModule,myapp.jackson.MyOtherModule"/>
</bean

Compatible with Jackson 2.9 to 2.12, as of Spring 5.3.

Author:Dmitry Katsubo, Rossen Stoyanchev, Brian Clozel, Juergen Hoeller, Tadaya Tsuyukubo, Sebastien Deleuze
Since:3.2
/** * A {@link FactoryBean} for creating a Jackson 2.x {@link ObjectMapper} (default) or * {@link XmlMapper} ({@code createXmlMapper} property set to true) with setters * to enable or disable Jackson features from within XML configuration. * * <p>It customizes Jackson defaults properties with the following ones: * <ul> * <li>{@link MapperFeature#DEFAULT_VIEW_INCLUSION} is disabled</li> * <li>{@link DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES} is disabled</li> * </ul> * * <p>Example usage with * {@link MappingJackson2HttpMessageConverter}: * * <pre class="code"> * &lt;bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> * &lt;property name="objectMapper"> * &lt;bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" * p:autoDetectFields="false" * p:autoDetectGettersSetters="false" * p:annotationIntrospector-ref="jaxbAnnotationIntrospector" /> * &lt;/property> * &lt;/bean> * </pre> * * <p>Example usage with MappingJackson2JsonView: * * <pre class="code"> * &lt;bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"> * &lt;property name="objectMapper"> * &lt;bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" * p:failOnEmptyBeans="false" * p:indentOutput="true"> * &lt;property name="serializers"> * &lt;array> * &lt;bean class="org.mycompany.MyCustomSerializer" /> * &lt;/array> * &lt;/property> * &lt;/bean> * &lt;/property> * &lt;/bean> * </pre> * * <p>In case there are no specific setters provided (for some rarely used options), * you can still use the more general methods {@link #setFeaturesToEnable} and * {@link #setFeaturesToDisable}. * * <pre class="code"> * &lt;bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> * &lt;property name="featuresToEnable"> * &lt;array> * &lt;util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRAP_ROOT_VALUE"/> * &lt;util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.CLOSE_CLOSEABLE"/> * &lt;/array> * &lt;/property> * &lt;property name="featuresToDisable"> * &lt;array> * &lt;util:constant static-field="com.fasterxml.jackson.databind.MapperFeature.USE_ANNOTATIONS"/> * &lt;/array> * &lt;/property> * &lt;/bean> * </pre> * * <p>It also automatically registers the following well-known modules if they are * detected on the classpath: * <ul> * <li><a href="https://github.com/FasterXML/jackson-datatype-jdk7">jackson-datatype-jdk7</a>: * support for Java 7 types like {@link java.nio.file.Path}</li> * <li><a href="https://github.com/FasterXML/jackson-datatype-jdk8">jackson-datatype-jdk8</a>: * support for other Java 8 types like {@link java.util.Optional}</li> * <li><a href="https://github.com/FasterXML/jackson-datatype-jsr310">jackson-datatype-jsr310</a>: * support for Java 8 Date & Time API types</li> * <li><a href="https://github.com/FasterXML/jackson-datatype-joda">jackson-datatype-joda</a>: * support for Joda-Time types</li> * <li><a href="https://github.com/FasterXML/jackson-module-kotlin">jackson-module-kotlin</a>: * support for Kotlin classes and data classes</li> * </ul> * * <p>In case you want to configure Jackson's {@link ObjectMapper} with a custom {@link Module}, * you can register one or more such Modules by class name via {@link #setModulesToInstall}: * * <pre class="code"> * &lt;bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> * &lt;property name="modulesToInstall" value="myapp.jackson.MySampleModule,myapp.jackson.MyOtherModule"/> * &lt;/bean * </pre> * * <p>Compatible with Jackson 2.9 to 2.12, as of Spring 5.3. * * @author <a href="mailto:dmitry.katsubo@gmail.com">Dmitry Katsubo</a> * @author Rossen Stoyanchev * @author Brian Clozel * @author Juergen Hoeller * @author Tadaya Tsuyukubo * @author Sebastien Deleuze * @since 3.2 */
public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper>, BeanClassLoaderAware, ApplicationContextAware, InitializingBean { private final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); @Nullable private ObjectMapper objectMapper;
Set the ObjectMapper instance to use. If not set, the ObjectMapper will be created using its default constructor.
/** * Set the {@link ObjectMapper} instance to use. If not set, the {@link ObjectMapper} * will be created using its default constructor. */
public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; }
If set to true and no custom ObjectMapper has been set, a XmlMapper will be created using its default constructor.
Since:4.1
/** * If set to true and no custom {@link ObjectMapper} has been set, a {@link XmlMapper} * will be created using its default constructor. * @since 4.1 */
public void setCreateXmlMapper(boolean createXmlMapper) { this.builder.createXmlMapper(createXmlMapper); }
Define the JsonFactory to be used to create the ObjectMapper instance.
Since:5.0
/** * Define the {@link JsonFactory} to be used to create the {@link ObjectMapper} * instance. * @since 5.0 */
public void setFactory(JsonFactory factory) { this.builder.factory(factory); }
Define the format for date/time with the given DateFormat.

Note: Setting this property makes the exposed ObjectMapper non-thread-safe, according to Jackson's thread safety rules.

See Also:
/** * Define the format for date/time with the given {@link DateFormat}. * <p>Note: Setting this property makes the exposed {@link ObjectMapper} * non-thread-safe, according to Jackson's thread safety rules. * @see #setSimpleDateFormat(String) */
public void setDateFormat(DateFormat dateFormat) { this.builder.dateFormat(dateFormat); }
Define the date/time format with a SimpleDateFormat.

Note: Setting this property makes the exposed ObjectMapper non-thread-safe, according to Jackson's thread safety rules.

See Also:
/** * Define the date/time format with a {@link SimpleDateFormat}. * <p>Note: Setting this property makes the exposed {@link ObjectMapper} * non-thread-safe, according to Jackson's thread safety rules. * @see #setDateFormat(DateFormat) */
public void setSimpleDateFormat(String format) { this.builder.simpleDateFormat(format); }
Override the default Locale to use for formatting. Default value used is Locale.getDefault().
Since:4.1.5
/** * Override the default {@link Locale} to use for formatting. * Default value used is {@link Locale#getDefault()}. * @since 4.1.5 */
public void setLocale(Locale locale) { this.builder.locale(locale); }
Override the default TimeZone to use for formatting. Default value used is UTC (NOT local timezone).
Since:4.1.5
/** * Override the default {@link TimeZone} to use for formatting. * Default value used is UTC (NOT local timezone). * @since 4.1.5 */
public void setTimeZone(TimeZone timeZone) { this.builder.timeZone(timeZone); }
Set an AnnotationIntrospector for both serialization and deserialization.
/** * Set an {@link AnnotationIntrospector} for both serialization and deserialization. */
public void setAnnotationIntrospector(AnnotationIntrospector annotationIntrospector) { this.builder.annotationIntrospector(annotationIntrospector); }
Specify a PropertyNamingStrategy to configure the ObjectMapper with.
Since:4.0.2
/** * Specify a {@link com.fasterxml.jackson.databind.PropertyNamingStrategy} to * configure the {@link ObjectMapper} with. * @since 4.0.2 */
public void setPropertyNamingStrategy(PropertyNamingStrategy propertyNamingStrategy) { this.builder.propertyNamingStrategy(propertyNamingStrategy); }
Specify a TypeResolverBuilder to use for Jackson's default typing.
Since:4.2.2
/** * Specify a {@link TypeResolverBuilder} to use for Jackson's default typing. * @since 4.2.2 */
public void setDefaultTyping(TypeResolverBuilder<?> typeResolverBuilder) { this.builder.defaultTyping(typeResolverBuilder); }
Set a custom inclusion strategy for serialization.
See Also:
  • Include
/** * Set a custom inclusion strategy for serialization. * @see com.fasterxml.jackson.annotation.JsonInclude.Include */
public void setSerializationInclusion(JsonInclude.Include serializationInclusion) { this.builder.serializationInclusion(serializationInclusion); }
Set the global filters to use in order to support @JsonFilter annotated POJO.
See Also:
  • Jackson2ObjectMapperBuilder.filters(FilterProvider)
Since:4.2
/** * Set the global filters to use in order to support {@link JsonFilter @JsonFilter} annotated POJO. * @since 4.2 * @see Jackson2ObjectMapperBuilder#filters(FilterProvider) */
public void setFilters(FilterProvider filters) { this.builder.filters(filters); }
Add mix-in annotations to use for augmenting specified class or interface.
Params:
  • mixIns – a Map of entries with target classes (or interface) whose annotations to effectively override as key and mix-in classes (or interface) whose annotations are to be "added" to target's annotations as value.
See Also:
  • addMixInAnnotations.addMixInAnnotations(Class, Class)
Since:4.1.2
/** * Add mix-in annotations to use for augmenting specified class or interface. * @param mixIns a Map of entries with target classes (or interface) whose annotations * to effectively override as key and mix-in classes (or interface) whose * annotations are to be "added" to target's annotations as value. * @since 4.1.2 * @see com.fasterxml.jackson.databind.ObjectMapper#addMixInAnnotations(Class, Class) */
public void setMixIns(Map<Class<?>, Class<?>> mixIns) { this.builder.mixIns(mixIns); }
Configure custom serializers. Each serializer is registered for the type returned by handledType.handledType(), which must not be null.
See Also:
  • setSerializersByType(Map)
/** * Configure custom serializers. Each serializer is registered for the type * returned by {@link JsonSerializer#handledType()}, which must not be {@code null}. * @see #setSerializersByType(Map) */
public void setSerializers(JsonSerializer<?>... serializers) { this.builder.serializers(serializers); }
Configure custom serializers for the given types.
See Also:
  • setSerializers(JsonSerializer...)
/** * Configure custom serializers for the given types. * @see #setSerializers(JsonSerializer...) */
public void setSerializersByType(Map<Class<?>, JsonSerializer<?>> serializers) { this.builder.serializersByType(serializers); }
Configure custom deserializers. Each deserializer is registered for the type returned by handledType.handledType(), which must not be null.
See Also:
  • setDeserializersByType(Map)
Since:4.3
/** * Configure custom deserializers. Each deserializer is registered for the type * returned by {@link JsonDeserializer#handledType()}, which must not be {@code null}. * @since 4.3 * @see #setDeserializersByType(Map) */
public void setDeserializers(JsonDeserializer<?>... deserializers) { this.builder.deserializers(deserializers); }
Configure custom deserializers for the given types.
/** * Configure custom deserializers for the given types. */
public void setDeserializersByType(Map<Class<?>, JsonDeserializer<?>> deserializers) { this.builder.deserializersByType(deserializers); }
Shortcut for AUTO_DETECT_FIELDS.AUTO_DETECT_FIELDS option.
/** * Shortcut for {@link MapperFeature#AUTO_DETECT_FIELDS} option. */
public void setAutoDetectFields(boolean autoDetectFields) { this.builder.autoDetectFields(autoDetectFields); }
Shortcut for AUTO_DETECT_SETTERS.AUTO_DETECT_SETTERS/ AUTO_DETECT_GETTERS.AUTO_DETECT_GETTERS/AUTO_DETECT_IS_GETTERS.AUTO_DETECT_IS_GETTERS options.
/** * Shortcut for {@link MapperFeature#AUTO_DETECT_SETTERS}/ * {@link MapperFeature#AUTO_DETECT_GETTERS}/{@link MapperFeature#AUTO_DETECT_IS_GETTERS} * options. */
public void setAutoDetectGettersSetters(boolean autoDetectGettersSetters) { this.builder.autoDetectGettersSetters(autoDetectGettersSetters); }
Shortcut for DEFAULT_VIEW_INCLUSION.DEFAULT_VIEW_INCLUSION option.
Since:4.1
/** * Shortcut for {@link MapperFeature#DEFAULT_VIEW_INCLUSION} option. * @since 4.1 */
public void setDefaultViewInclusion(boolean defaultViewInclusion) { this.builder.defaultViewInclusion(defaultViewInclusion); }
Shortcut for FAIL_ON_UNKNOWN_PROPERTIES.FAIL_ON_UNKNOWN_PROPERTIES option.
Since:4.1.1
/** * Shortcut for {@link DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES} option. * @since 4.1.1 */
public void setFailOnUnknownProperties(boolean failOnUnknownProperties) { this.builder.failOnUnknownProperties(failOnUnknownProperties); }
Shortcut for FAIL_ON_EMPTY_BEANS.FAIL_ON_EMPTY_BEANS option.
/** * Shortcut for {@link SerializationFeature#FAIL_ON_EMPTY_BEANS} option. */
public void setFailOnEmptyBeans(boolean failOnEmptyBeans) { this.builder.failOnEmptyBeans(failOnEmptyBeans); }
Shortcut for INDENT_OUTPUT.INDENT_OUTPUT option.
/** * Shortcut for {@link SerializationFeature#INDENT_OUTPUT} option. */
public void setIndentOutput(boolean indentOutput) { this.builder.indentOutput(indentOutput); }
Define if a wrapper will be used for indexed (List, array) properties or not by default (only applies to XmlMapper).
Since:4.3
/** * Define if a wrapper will be used for indexed (List, array) properties or not by * default (only applies to {@link XmlMapper}). * @since 4.3 */
public void setDefaultUseWrapper(boolean defaultUseWrapper) { this.builder.defaultUseWrapper(defaultUseWrapper); }
Specify features to enable.
See Also:
  • Feature
  • Feature
  • SerializationFeature
  • DeserializationFeature
  • MapperFeature
/** * Specify features to enable. * @see com.fasterxml.jackson.core.JsonParser.Feature * @see com.fasterxml.jackson.core.JsonGenerator.Feature * @see com.fasterxml.jackson.databind.SerializationFeature * @see com.fasterxml.jackson.databind.DeserializationFeature * @see com.fasterxml.jackson.databind.MapperFeature */
public void setFeaturesToEnable(Object... featuresToEnable) { this.builder.featuresToEnable(featuresToEnable); }
Specify features to disable.
See Also:
  • Feature
  • Feature
  • SerializationFeature
  • DeserializationFeature
  • MapperFeature
/** * Specify features to disable. * @see com.fasterxml.jackson.core.JsonParser.Feature * @see com.fasterxml.jackson.core.JsonGenerator.Feature * @see com.fasterxml.jackson.databind.SerializationFeature * @see com.fasterxml.jackson.databind.DeserializationFeature * @see com.fasterxml.jackson.databind.MapperFeature */
public void setFeaturesToDisable(Object... featuresToDisable) { this.builder.featuresToDisable(featuresToDisable); }
Set a complete list of modules to be registered with the ObjectMapper.

Note: If this is set, no finding of modules is going to happen - not by Jackson, and not by Spring either (see setFindModulesViaServiceLoader). As a consequence, specifying an empty list here will suppress any kind of module detection.

Specify either this or setModulesToInstall, not both.

See Also:
  • Module
Since:4.0
/** * Set a complete list of modules to be registered with the {@link ObjectMapper}. * <p>Note: If this is set, no finding of modules is going to happen - not by * Jackson, and not by Spring either (see {@link #setFindModulesViaServiceLoader}). * As a consequence, specifying an empty list here will suppress any kind of * module detection. * <p>Specify either this or {@link #setModulesToInstall}, not both. * @since 4.0 * @see com.fasterxml.jackson.databind.Module */
public void setModules(List<Module> modules) { this.builder.modules(modules); }
Specify one or more modules by class (or class name in XML) to be registered with the ObjectMapper.

Modules specified here will be registered after Spring's autodetection of JSR-310 and Joda-Time, or Jackson's finding of modules (see setFindModulesViaServiceLoader), allowing to eventually override their configuration.

Specify either this or setModules, not both.

See Also:
  • Module
Since:4.0.1
/** * Specify one or more modules by class (or class name in XML) * to be registered with the {@link ObjectMapper}. * <p>Modules specified here will be registered after * Spring's autodetection of JSR-310 and Joda-Time, or Jackson's * finding of modules (see {@link #setFindModulesViaServiceLoader}), * allowing to eventually override their configuration. * <p>Specify either this or {@link #setModules}, not both. * @since 4.0.1 * @see com.fasterxml.jackson.databind.Module */
@SafeVarargs public final void setModulesToInstall(Class<? extends Module>... modules) { this.builder.modulesToInstall(modules); }
Set whether to let Jackson find available modules via the JDK ServiceLoader, based on META-INF metadata in the classpath. Requires Jackson 2.2 or higher.

If this mode is not set, Spring's Jackson2ObjectMapperFactoryBean itself will try to find the JSR-310 and Joda-Time support modules on the classpath - provided that Java 8 and Joda-Time themselves are available, respectively.

See Also:
  • findModules.findModules()
Since:4.0.1
/** * Set whether to let Jackson find available modules via the JDK ServiceLoader, * based on META-INF metadata in the classpath. Requires Jackson 2.2 or higher. * <p>If this mode is not set, Spring's Jackson2ObjectMapperFactoryBean itself * will try to find the JSR-310 and Joda-Time support modules on the classpath - * provided that Java 8 and Joda-Time themselves are available, respectively. * @since 4.0.1 * @see com.fasterxml.jackson.databind.ObjectMapper#findModules() */
public void setFindModulesViaServiceLoader(boolean findModules) { this.builder.findModulesViaServiceLoader(findModules); } @Override public void setBeanClassLoader(ClassLoader beanClassLoader) { this.builder.moduleClassLoader(beanClassLoader); }
Customize the construction of Jackson handlers (JsonSerializer, JsonDeserializer, KeyDeserializer, TypeResolverBuilder and TypeIdResolver).
See Also:
  • setApplicationContext(ApplicationContext)
Since:4.1.3
/** * Customize the construction of Jackson handlers * ({@link JsonSerializer}, {@link JsonDeserializer}, {@link KeyDeserializer}, * {@code TypeResolverBuilder} and {@code TypeIdResolver}). * @since 4.1.3 * @see Jackson2ObjectMapperFactoryBean#setApplicationContext(ApplicationContext) */
public void setHandlerInstantiator(HandlerInstantiator handlerInstantiator) { this.builder.handlerInstantiator(handlerInstantiator); }
Set the builder ApplicationContext in order to autowire Jackson handlers (JsonSerializer, JsonDeserializer, KeyDeserializer, TypeResolverBuilder and TypeIdResolver).
See Also:
Since:4.1.3
/** * Set the builder {@link ApplicationContext} in order to autowire Jackson handlers * ({@link JsonSerializer}, {@link JsonDeserializer}, {@link KeyDeserializer}, * {@code TypeResolverBuilder} and {@code TypeIdResolver}). * @since 4.1.3 * @see Jackson2ObjectMapperBuilder#applicationContext(ApplicationContext) * @see SpringHandlerInstantiator */
@Override public void setApplicationContext(ApplicationContext applicationContext) { this.builder.applicationContext(applicationContext); } @Override public void afterPropertiesSet() { if (this.objectMapper != null) { this.builder.configure(this.objectMapper); } else { this.objectMapper = this.builder.build(); } }
Return the singleton ObjectMapper.
/** * Return the singleton ObjectMapper. */
@Override @Nullable public ObjectMapper getObject() { return this.objectMapper; } @Override public Class<?> getObjectType() { return (this.objectMapper != null ? this.objectMapper.getClass() : null); } @Override public boolean isSingleton() { return true; } }