Created
October 1, 2014 07:40
-
-
Save sdeleuze/23548ff318e0c75e912a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2012-2014 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 | |
* | |
* http://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.boot.autoconfigure.jackson; | |
import java.util.Collection; | |
import java.util.Map.Entry; | |
import javax.annotation.PostConstruct; | |
import org.springframework.beans.factory.BeanFactoryUtils; | |
import org.springframework.beans.factory.ListableBeanFactory; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.JavaVersion; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |
import org.springframework.boot.autoconfigure.web.HttpMapperProperties; | |
import org.springframework.boot.context.properties.EnableConfigurationProperties; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.context.annotation.Primary; | |
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; | |
import com.fasterxml.jackson.core.JsonGenerator; | |
import com.fasterxml.jackson.core.JsonParser; | |
import com.fasterxml.jackson.databind.DeserializationFeature; | |
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.dataformat.xml.XmlMapper; | |
import com.fasterxml.jackson.datatype.joda.JodaModule; | |
import com.fasterxml.jackson.datatype.jsr310.JSR310Module; | |
/** | |
* Auto configuration for Jackson. The following auto-configuration will get applied: | |
* <ul> | |
* <li>an {@link ObjectMapper} in case none is already configured.</li> | |
* <li>the {@link JodaModule} registered if it's on the classpath.</li> | |
* <li>the {@link JSR310Module} registered if it's on the classpath and the application is | |
* running on Java 8 or better.</li> | |
* <li>auto-registration for all {@link Module} beans with all {@link ObjectMapper} beans | |
* (including the defaulted ones).</li> | |
* </ul> | |
* | |
* @author Oliver Gierke | |
* @author Andy Wilkinson | |
* @author Sebastien Deleuze | |
* @since 1.1.0 | |
*/ | |
@Configuration | |
@ConditionalOnClass(ObjectMapper.class) | |
public class JacksonAutoConfiguration { | |
@Autowired | |
private ListableBeanFactory beanFactory; | |
@PostConstruct | |
private void registerModulesWithObjectMappers() { | |
Collection<Module> modules = getBeans(Module.class); | |
for (ObjectMapper objectMapper : getBeans(ObjectMapper.class)) { | |
objectMapper.registerModules(modules); | |
} | |
} | |
private <T> Collection<T> getBeans(Class<T> type) { | |
return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type) | |
.values(); | |
} | |
@Configuration | |
@ConditionalOnClass(ObjectMapper.class) | |
@EnableConfigurationProperties({ HttpMapperProperties.class, JacksonProperties.class }) | |
static class JacksonObjectMapperAutoConfiguration extends AbstractJacksonObjectMapperConfiguration { | |
@Bean | |
@Primary | |
@ConditionalOnMissingBean | |
public ObjectMapper jacksonObjectMapper() { | |
ObjectMapper objectMapper = new ObjectMapper(); | |
if (this.httpMapperProperties.isJsonSortKeys()) { | |
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, | |
true); | |
} | |
configureDeserializationFeatures(objectMapper); | |
configureSerializationFeatures(objectMapper); | |
configureMapperFeatures(objectMapper); | |
configureParserFeatures(objectMapper); | |
configureGeneratorFeatures(objectMapper); | |
return objectMapper; | |
} | |
@Bean | |
@Primary | |
@ConditionalOnMissingBean | |
public ObjectMapper jacksonObjectMapper2() { | |
ObjectMapper objectMapper = new ObjectMapper(); | |
if (this.httpMapperProperties.isJsonSortKeys()) { | |
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, | |
true); | |
} | |
configureDeserializationFeatures(objectMapper); | |
configureSerializationFeatures(objectMapper); | |
configureMapperFeatures(objectMapper); | |
configureParserFeatures(objectMapper); | |
configureGeneratorFeatures(objectMapper); | |
return objectMapper; | |
} | |
} | |
@Configuration | |
@ConditionalOnClass(XmlMapper.class) | |
@EnableConfigurationProperties({ HttpMapperProperties.class, JacksonProperties.class }) | |
static class JacksonXmlMapperAutoConfiguration extends AbstractJacksonObjectMapperConfiguration { | |
@Bean | |
@ConditionalOnMissingBean | |
public XmlMapper jacksonXmlMapper() { | |
XmlMapper xmlMapper = Jackson2ObjectMapperBuilder.xml().build(); | |
if (this.httpMapperProperties.isJsonSortKeys()) { | |
xmlMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); | |
} | |
configureDeserializationFeatures(xmlMapper); | |
configureSerializationFeatures(xmlMapper); | |
configureMapperFeatures(xmlMapper); | |
configureParserFeatures(xmlMapper); | |
configureGeneratorFeatures(xmlMapper); | |
return xmlMapper; | |
} | |
} | |
static abstract class AbstractJacksonObjectMapperConfiguration { | |
@Autowired | |
protected HttpMapperProperties httpMapperProperties = new HttpMapperProperties(); | |
@Autowired | |
protected JacksonProperties jacksonProperties = new JacksonProperties(); | |
protected void configureDeserializationFeatures(ObjectMapper objectMapper) { | |
for (Entry<DeserializationFeature, Boolean> entry : this.jacksonProperties | |
.getDeserialization().entrySet()) { | |
objectMapper.configure(entry.getKey(), isFeatureEnabled(entry)); | |
} | |
} | |
protected void configureSerializationFeatures(ObjectMapper objectMapper) { | |
for (Entry<SerializationFeature, Boolean> entry : this.jacksonProperties | |
.getSerialization().entrySet()) { | |
objectMapper.configure(entry.getKey(), isFeatureEnabled(entry)); | |
} | |
} | |
protected void configureMapperFeatures(ObjectMapper objectMapper) { | |
for (Entry<MapperFeature, Boolean> entry : this.jacksonProperties.getMapper() | |
.entrySet()) { | |
objectMapper.configure(entry.getKey(), isFeatureEnabled(entry)); | |
} | |
} | |
protected void configureParserFeatures(ObjectMapper objectMapper) { | |
for (Entry<JsonParser.Feature, Boolean> entry : this.jacksonProperties | |
.getParser().entrySet()) { | |
objectMapper.configure(entry.getKey(), isFeatureEnabled(entry)); | |
} | |
} | |
protected void configureGeneratorFeatures(ObjectMapper objectMapper) { | |
for (Entry<JsonGenerator.Feature, Boolean> entry : this.jacksonProperties | |
.getGenerator().entrySet()) { | |
objectMapper.configure(entry.getKey(), isFeatureEnabled(entry)); | |
} | |
} | |
protected boolean isFeatureEnabled(Entry<?, Boolean> entry) { | |
return entry.getValue() != null && entry.getValue(); | |
} | |
} | |
@Configuration | |
@ConditionalOnClass(JodaModule.class) | |
static class JodaModuleAutoConfiguration { | |
@Bean | |
@ConditionalOnMissingBean | |
public JodaModule jacksonJodaModule() { | |
return new JodaModule(); | |
} | |
} | |
@Configuration | |
@ConditionalOnJava(JavaVersion.EIGHT) | |
@ConditionalOnClass(JSR310Module.class) | |
static class Jsr310ModuleAutoConfiguration { | |
@Bean | |
@ConditionalOnMissingBean | |
public JSR310Module jacksonJsr310Module() { | |
return new JSR310Module(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment