Add Jackson's Modules registration in Jackson2OMFactoryBean

Prior to this commit, one couldn't configure Jackson's ObjectMapper
with (De)SerializerModifiers or advanced configuration features
using XML configuration.

This commit updates the FactoryBean and adds a setModule method
that will register Modules with the ObjectMapper.

Note that this commit is only about XML configuration, since
this feature was already available with JavaConfig.

Issue: SPR-10429
This commit is contained in:
Brian Clozel 2013-10-02 15:43:42 +02:00 committed by Rossen Stoyanchev
parent e91ce23cd0
commit a5e3916724
2 changed files with 54 additions and 1 deletions

View File

@ -18,8 +18,10 @@ package org.springframework.http.converter.json;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.FatalBeanException;
@ -35,6 +37,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
@ -95,8 +98,22 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
* </bean>
* </pre>
*
* In case you want to configure Jackson's {@link ObjectMapper} with a {@link Module}, you
* can register Modules using {@link #setModules(java.util.List)}
*
* <pre class="code">
* &lt;bean class="org.springframework.web.context.support.Jackson2ObjectMapperFactoryBean">
* &lt;property name="modules"&gt;
* &lt;list&gt;
* &lt;bean class="org.example.jackson.module.MySampleModule"/&gt;
* &lt;/list&gt;
* &lt;/property&gt;
* &lt;/bean>
* </pre>
*
* @author <a href="mailto:dmitry.katsubo@gmail.com">Dmitry Katsubo</a>
* @author Rossen Stoyanchev
* @author Brian Clozel
* @since 3.2
*/
public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper>, InitializingBean {
@ -105,6 +122,8 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
private Map<Object, Boolean> features = new HashMap<Object, Boolean>();
private final List<Module> modules = new ArrayList<Module>();
private DateFormat dateFormat;
private AnnotationIntrospector annotationIntrospector;
@ -258,6 +277,18 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
this.serializationInclusion = serializationInclusion;
}
/**
* Sets the list of modules to be registered with {@link ObjectMapper}.
* @param modules the list of modules
* @see com.fasterxml.jackson.databind.Module
* @since 4.0
*/
public void setModules(List<Module> modules) {
if(modules != null) {
this.modules.addAll(modules);
}
}
@Override
public void afterPropertiesSet() {
if (this.objectMapper == null) {
@ -286,6 +317,10 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
if (this.serializationInclusion != null) {
this.objectMapper.setSerializationInclusion(this.serializationInclusion);
}
if(!this.modules.isEmpty()) {
this.objectMapper.registerModules(this.modules);
}
}
@SuppressWarnings("unchecked")

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@ -17,6 +17,7 @@
package org.springframework.http.converter.json;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@ -33,6 +34,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
@ -40,6 +42,7 @@ import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
import com.fasterxml.jackson.databind.deser.BasicDeserializerFactory;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers.DateDeserializer;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BasicSerializerFactory;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.fasterxml.jackson.databind.ser.std.NumberSerializers.NumberSerializer;
@ -52,6 +55,7 @@ import static org.junit.Assert.*;
* Test cases for {@link Jackson2ObjectMapperFactoryBean} class.
*
* @author <a href="mailto:dmitry.katsubo@gmail.com">Dmitry Katsubo</a>
* @author Brian Clozel
*/
public class Jackson2ObjectMapperFactoryBeanTests {
@ -151,6 +155,20 @@ public class Jackson2ObjectMapperFactoryBeanTests {
assertEquals(dateFormat, this.factory.getObject().getDeserializationConfig().getDateFormat());
}
@Test
public void testSetModules() {
JsonSerializer serializer1 = new NumberSerializer();
SimpleModule module = new SimpleModule();
module.addSerializer(Boolean.class,serializer1);
this.factory.setModules(Arrays.asList(new Module[]{module}));
this.factory.afterPropertiesSet();
ObjectMapper objectMapper = this.factory.getObject();
Serializers serializers = getSerializerFactoryConfig(objectMapper).serializers().iterator().next();
assertTrue(serializers.findSerializer(null, SimpleType.construct(Boolean.class), null) == serializer1);
}
@Test
public void testSimpleSetup() {
this.factory.afterPropertiesSet();