springboot jackson默认配置

springboot jackson默认配置

​ springboot是约定大约配置,默认就会进行比较合理的配置,自动配置jackson也是如此。下面看一下springboot是如何配置jackson的反序列化特性的。

配置jackson的方法

​ 想要自定义配置jackson,只需实现Jackson2ObjectMapperBuilderCustomizer接口,并注册到spring容器里即可。

平时我们主要关注下面两个配置,一个是序列化时不返回值为null的字段,二是反序列化时遇到不认识的key不报错而是忽略此key。

1
2
3
4
5
6
7
8
9
10
@Configuration
public class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer {

@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
jacksonObjectMapperBuilder.failOnUnknownProperties(false);
}

}

自动配置的jackson配置

如果没提供自定义的配置,将只使用springboot的默认配置,在JacksonAutoConfiguration类中,存在如下代码

1
2
3
4
5
6
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder.createXmlMapper(false).build();
}

可见其实使用Jackson2ObjectMapperBuilder类来创建ObjectMapper,且关闭了xml功能。

Jackson2ObjectMapperBuilder的创建同样在此类中,因为我们没有传入任何自定义Jackson2ObjectMapperBuilderCustomizer,所以其使用默认的值。

1
2
3
4
5
6
7
8
9
@Bean
@ConditionalOnMissingBean(Jackson2ObjectMapperBuilder.class)
public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(
List<Jackson2ObjectMapperBuilderCustomizer> customizers) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.applicationContext(this.applicationContext);
customize(builder, customizers);
return builder;
}

查看Jackson2ObjectMapperBuilder类内部的build方法源码,其也是创建一个新的ObjectMapper并对其进行配置,重点就在下面源码的configure(mapper)方法里面。

1
2
3
4
5
6
7
8
9
10
11
12
13
public <T extends ObjectMapper> T build() {
ObjectMapper mapper;
if (this.createXmlMapper) {
mapper = (this.defaultUseWrapper != null ?
new XmlObjectMapperInitializer().create(this.defaultUseWrapper) :
new XmlObjectMapperInitializer().create());
}
else {
mapper = new ObjectMapper();
}
configure(mapper);
return (T) mapper;
}

​ 进入configure方法里,其将此构建器的属性进行非空判断,如果不为空就设置到ObjectMapper里。因为我们没有提供任何自定义配置,所以这些值都是空的,其中此方法里有一行调用了customizeDefaultFeatures(objectMapper)方法,其会设置默认配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public void configure(ObjectMapper objectMapper) {
Assert.notNull(objectMapper, "ObjectMapper must not be null");

if (this.findModulesViaServiceLoader) {
// Jackson 2.2+
objectMapper.registerModules(ObjectMapper.findModules(this.moduleClassLoader));
}
else if (this.findWellKnownModules) {
registerWellKnownModulesIfAvailable(objectMapper);
}

if (this.modules != null) {
for (Module module : this.modules) {
// Using Jackson 2.0+ registerModule method, not Jackson 2.2+ registerModules
objectMapper.registerModule(module);
}
}
if (this.moduleClasses != null) {
for (Class<? extends Module> module : this.moduleClasses) {
objectMapper.registerModule(BeanUtils.instantiate(module));
}
}

if (this.dateFormat != null) {
objectMapper.setDateFormat(this.dateFormat);
}
if (this.locale != null) {
objectMapper.setLocale(this.locale);
}
if (this.timeZone != null) {
objectMapper.setTimeZone(this.timeZone);
}

if (this.annotationIntrospector != null) {
objectMapper.setAnnotationIntrospector(this.annotationIntrospector);
}
if (this.propertyNamingStrategy != null) {
objectMapper.setPropertyNamingStrategy(this.propertyNamingStrategy);
}
if (this.defaultTyping != null) {
objectMapper.setDefaultTyping(this.defaultTyping);
}
if (this.serializationInclusion != null) {
objectMapper.setSerializationInclusion(this.serializationInclusion);
}

if (this.filters != null) {
objectMapper.setFilterProvider(this.filters);
}

for (Class<?> target : this.mixIns.keySet()) {
objectMapper.addMixIn(target, this.mixIns.get(target));
}

if (!this.serializers.isEmpty() || !this.deserializers.isEmpty()) {
SimpleModule module = new SimpleModule();
addSerializers(module);
addDeserializers(module);
objectMapper.registerModule(module);
}

customizeDefaultFeatures(objectMapper);
for (Object feature : this.features.keySet()) {
configureFeature(objectMapper, feature, this.features.get(feature));
}

if (this.handlerInstantiator != null) {
objectMapper.setHandlerInstantiator(this.handlerInstantiator);
}
else if (this.applicationContext != null) {
objectMapper.setHandlerInstantiator(
new SpringHandlerInstantiator(this.applicationContext.getAutowireCapableBeanFactory()));
}
}

​ 可以看到当features里面不包含FAIL_ON_UNKNOWN_PROPERTIES时,即我们没有主动将FAIL_ON_UNKNOWN_PROPERTIES设为true或者false,springboot会将其设置为false,这也正符合我们平时的使用习惯。

1
2
3
4
5
6
7
8
9
private void customizeDefaultFeatures(ObjectMapper objectMapper) {
if (!this.features.containsKey(MapperFeature.DEFAULT_VIEW_INCLUSION)) {
configureFeature(objectMapper, MapperFeature.DEFAULT_VIEW_INCLUSION, false);
}
//列表内找不到该属性,就将此属性设置为false
if (!this.features.containsKey(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
configureFeature(objectMapper, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}

总结

​ 上面可以看出springboot会为我们自动配置好比较合理的配置,即约定大于配置,我们没有FAIL_ON_UNKNOWN_PROPERTIES的配置时,他会自动将其设为false。

​ 于是我们在下次自定义配置时,不配置此属性也是可以的,将上面的配置改为下面这样,其也是能自动设置FAIL_ON_UNKNOWN_PROPERTIES=false的。

1
2
3
4
5
6
7
8
@Configuration
public class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer {

@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
}
}

​ 但是考虑到不是每个人都看过源码,还是推荐加上,这样其他人看到会更清晰一点。


springboot jackson默认配置
https://www.huangchaoyu.com/958846089.html
作者
hcy
发布于
2021年2月8日
更新于
2024年8月17日
许可协议