@JsonFormat @DateTimeFormat 区别与jackson全局序列化反序列化设置

@JsonFormat  @DateTimeFormat区别

①未使用全局jackson设置:测试form data传参

前端->后端 @DateTimeFormat  OK

后端->前端- @JsonFormat   OK

②未使用全局jackson设置:测试json传参(使用@ResbonseBody反序列化)

前端->后端 @DateTimeFormat  失效

后端->前端 @JsonFormat   OK,同时@JsonFormat前端->后端反序列化也生效

使用全局jackson设置,兼容原注解

主要解决以下几个全局性问题

①@Requestbody @Responsebody默认使用的是jackson序列化,反序列化,但是其默认常常无法满足我们的需求,如日期,时间类型常常需要使用@JsonFormat  @DateTimeFormat等注解来实现标准yyyy-MM-dd HH:mm:ss字符串与日期时间的转换。

② 常用的Long类型雪花ID 字段常常加@JsonSerialize(using = ToStringSerializer.class),将Long序列化为字符串,避免精度丢失;

③全局null字段不序列化等自定义设置等

/**
 * 后端->前端全局序列化设置:
 * 全局Long转String,LocalDateTime LocalDate LocalTime  java.util.Date序列化与反序列化
 * 可以通过实现WebMvcConfigurer接口
 * @author majun
 * @since 2020-08-21
 */
@Configuration
//@Primary
public class JacksonSerializerConfig  implements WebMvcConfigurer {
    private static final String PATTERN="yyyy-MM-dd HH:mm:ss";
    private static final String TIME_ZONE="GMT+8";

    @Override
    public void extendMessageConverters(List> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = converter.getObjectMapper();
        objectMapper.setTimeZone(TimeZone.getTimeZone(TIME_ZONE));
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //关闭日期序列化为时间戳的功能
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //关闭序列化的时候没有为属性找到getter方法,报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //序列化的时候序列对象的所有属性
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //空值不序列化
        //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //序列化空对象不抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //关闭反序列化的时候,没有找到属性的setter报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        //反序列化未知属性不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //自定义序列化:key-序列化字段类型,value-序列化所用对象,支持自定义及Jackson自带序列化器
        SimpleModule module = new SimpleModule();
        String[] patternArr = PATTERN.split(" ");
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(PATTERN)));
        module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(patternArr[0])));
        module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(patternArr[1])));
        module.addSerializer(Date.class, new DateSerializer(false,new SimpleDateFormat(PATTERN)));
        module.addSerializer(Long.class, ToStringSerializer.instance);
        //自定义反序列化:key-序列化字段类型,value-序列化所用对象,支持自定义及Jackson自带序列化器
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(PATTERN)));
        module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(patternArr[0])));
        module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(patternArr[1])));
        module.addDeserializer(Date.class, new DateDeserializers.DateDeserializer(){
            @SneakyThrows
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext ctxt){
               String text = jsonParser.getText().trim();
                SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
                return sdf.parse(text);
            }
        });
        objectMapper.registerModule(module);
        converters.add(0, converter);
    }
}

以上方式会出现使用@RequestBody String  params接收前端的application/json参数出现序列化错误,解决方案:

将springboot自动配置的MappingJackson2HttpMessageConverter找到进行再设置。

/**
 * 后端->前端全局序列化设置:
 * 全局Long转String,LocalDateTime LocalDate LocalTime  java.util.Date序列化与反序列化
 * 可以通过实现WebMvcConfigurer接口
 * @author majun
 * @since 2020-08-21
 */
@Configuration
//@Primary
public class JacksonSerializerConfiguration implements WebMvcConfigurer {

    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;
    @Value("${spring.jackson.time-zone:GMT+8}")
    private String timeZone;



    @Override
    public void extendMessageConverters(List> converters) {
        for (HttpMessageConverter cvt : converters) {
            if (cvt instanceof  MappingJackson2HttpMessageConverter) {
                MappingJackson2HttpMessageConverter converter= (MappingJackson2HttpMessageConverter) cvt;
                enhanceConvertor(converter);
            }

        }
        
    }

    private void enhanceConvertor(MappingJackson2HttpMessageConverter converter) {
        ObjectMapper objectMapper = converter.getObjectMapper();
        objectMapper.setTimeZone(TimeZone.getTimeZone(timeZone));
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //关闭日期序列化为时间戳的功能
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //关闭序列化的时候没有为属性找到getter方法,报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //序列化的时候序列对象的所有属性
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //空值不序列化
        //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //序列化空对象不抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //关闭反序列化的时候,没有找到属性的setter报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
        //反序列化未知属性不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //自定义序列化:key-序列化字段类型,value-序列化所用对象,支持自定义及Jackson自带序列化器
        SimpleModule module = new SimpleModule();
        String[] patternArr = pattern.split(" ");
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)));
        module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(patternArr[0])));
        module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(patternArr[1])));
        module.addSerializer(Date.class, new DateSerializer(false,new SimpleDateFormat(pattern)));
        //module.addSerializer(Long.class,ToStringSerializer.instance); // 会将mybatisplus 分页返回的total也转成字符串导致flutter问题
        // 自定义序列化:long长度超过18位则认为是雪花ID,转为string,否则为数字,
        module.addSerializer(Long.class, new JsonSerializer() {
            @Override
            public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                String str = String.valueOf(aLong);
                if (str.length()>=18) {
                    jsonGenerator.writeString(str);
                }else {
                    jsonGenerator.writeNumber(aLong);
                }
            }
        });
        //自定义反序列化:key-序列化字段类型,value-序列化所用对象,支持自定义及Jackson自带序列化器
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(pattern)));
        module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(patternArr[0])));
        module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(patternArr[1])));
        module.addDeserializer(Date.class, new DateDeserializers.DateDeserializer(){
            @SneakyThrows
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext ctxt){
                String text = jsonParser.getText().trim();
                SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                return sdf.parse(text);
            }
        });
        objectMapper.registerModule(module);
    }

}

 

你可能感兴趣的:(spring)