springboot jackson默认配置

Posted by hcy on February 8, 2021

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);
    }
}

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


转载请注明出处:https://www.huangchaoyu.com/2021/02/08/springboot-jackson默认配置/