目录

Spring Boot: 自定义 Jackson ObjectMapper

Spring Boot WebMvcConfigurationSupport#addDefaultHttpMessageConverters 会添加默认的 MappingJackson2HttpMessageConverter @RequestBody 参数为对象, @ResponseBody 返回为对象时都是使用这个 HttpMessageConverter。

JacksonAutoConfiguration 自动配置,查看源码学习。

默认

  • MapperFeature.DEFAULT_VIEW_INCLUSION
  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS

自定义默认 ObjectMapper

application properties 与 自定义 Jackson Module

spring.jackson.<category_name>.<feature_name>=true,false

spring.jackson.serialization.write-dates-as-timestamps=false
spring.jackson.default-property-inclusion=always, non_null, non_absent, non_default, non_empty
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Configuration
public class RegisterModuleConfig {

    @Bean
    public Module javaTimeModule() {
        JavaTimeModule module = new JavaTimeModule();
        module.addSerializer(LOCAL_DATETIME_SERIALIZER);
        return module;
    }
}

Jackson2ObjectMapperBuilderCustomizer

1
2
3
4
5
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
    return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)
      .serializers(LOCAL_DATETIME_SERIALIZER);
}

覆盖默认配置

ObjectMapper

1
2
3
4
5
6
7
8
9
@Bean
@Primary
public ObjectMapper objectMapper() {
    JavaTimeModule module = new JavaTimeModule();
    module.addSerializer(LOCAL_DATETIME_SERIALIZER);
    return new ObjectMapper()
      .setSerializationInclusion(JsonInclude.Include.NON_NULL)
      .registerModule(module);
}

jackson2ObjectMapperBuilder

1
2
3
4
5
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
    return new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATETIME_SERIALIZER)
      .serializationInclusion(JsonInclude.Include.NON_NULL);
}

MappingJackson2HttpMessageConverter

1
2
3
4
5
6
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATETIME_SERIALIZER)
      .serializationInclusion(JsonInclude.Include.NON_NULL);
    return new MappingJackson2HttpMessageConverter(builder.build());
}

自定义 SimpleModule

1
2
3
4
5
6
7
@Component
public class BigDecimalModual extends SimpleModule {
    public BigDecimalModual(){
        addSerializer(BigDecimal.class,new BigDecimalSerializer());
        addDeserializer(BigDecimal.class,new BigDecimalDeSerializer());
    }
}

BigDecimal 处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Configuration
public class JacksonConfig {
    @Bean
    @Primary
    public ObjectMapper bigDecimalObjectMapper(Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder){
        ObjectMapper objectMapper= jackson2ObjectMapperBuilder.build();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(BigDecimal.class,new NumberDeserializers.BigDecimalDeserializer());
        simpleModule.addSerializer(BigDecimal.class,new BigDecimalSerializer())
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

@JsonComponent

​ 这是最简单的方法,直接作用于全局,所有对BigDecima序列化和反序列化的时候都会使用这两个序列化和反序列类,简单实用。为了方便,在上面的序列化和反序列化类上直接加上了@JsonComponent。加了@JsonComponent的类会被一个JsonComponentModual加载。

 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
@JsonComponent
public class BigDecimalDeSerializer extends JsonDeserializer<BigDecimal> {
    @Override
    public BigDecimal deserialize(JsonParser jsonParser, 
                                  DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        //千分位分隔的数值从前端到后端是需要反序列化为BigDecimal。需要去掉“,”
        return new BigDecimal(jsonParser.getText().replaceAll(",",""));
    }
}

@JsonComponent
public class BigDecimalSerializer extends JsonSerializer<BigDecimal> implements ContextualSerializer {
    private String format = "###,##0.00";

    @Override
    public void serialize(BigDecimal bigDecimal, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(new DecimalFormat(format).format(bigDecimal));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if(beanProperty !=null ){
            if(Objects.equals(beanProperty.getType().getRawClass(),BigDecimal.class)){
                BigDecimalFormat bigDecimalFormat = beanProperty.getAnnotation((BigDecimalFormat.class));
                if(bigDecimalFormat == null){
                    bigDecimalFormat = beanProperty.getContextAnnotation(BigDecimalFormat.class);
                }
                BigDecimalSerializer bigDecimalSerializer = new BigDecimalSerializer();
                if(bigDecimalFormat != null){
                    bigDecimalSerializer.format = bigDecimalFormat.value();
                }
                return bigDecimalSerializer;
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(),beanProperty);
        }
        return serializerProvider.findNullValueSerializer(beanProperty);
    }
}