6

一文详解JackSon配置信息 - 无涯Ⅱ

 1 year ago
source link: https://www.cnblogs.com/wlandwl/p/jackson.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一文详解JackSon配置信息 - 无涯Ⅱ - 博客园

一文详解JackSon配置信息
Published on 2022-06-24 14:19 in 暂未分类 with 无涯Ⅱ

1.1 问题

Spring Boot 在处理对象的序列化和反序列化时,默认使用框架自带的JackSon配置。使用框架默认的,通常会面临如下问题:
  1. Date返回日期格式(建议不使用Date,但老项目要兼容),带有T,如 2018-05-15T24:59:59:
  1. LocalDate返回日期对象为数组(框架中继承了 WebMvcConfigurationSupport);
  1. LocalDateTime时间转换失败等;
  1. 定义了日期类型,如LocalDate,前端对接时(post/get),如果传入日期字符串("2022-05-05"),会报String 转换为LocalDate失败;
  1. 返回long型数据,前端js存在精度问题,需做转换;
  1. 一些特殊对象要做业务特殊转换,如加解密等;

1.2 解决方案

针对上述问题,存在很多种解决方案。由于底层框架统一配置拦截类实现的模式不同,还是会存在差异,本文主要说明在不同的配置场景下,自定义Jackson配置的一些注意事项和差异化原因:
为了解决特殊对象(如日期)的序列化和反序列化问题,常用方案如下:
  1. 针对特殊的具体对象,在对象上面使用注解,如:
@JsonSerialize(using= JsonDateSerializer.class)
private Date taskEndTime;

@ApiModelProperty(value = "检查日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate checkDate;
  1. 重新实现WebMvcConfigurer接口,自定义JackSon配置。
  1. 继承 WebMvcConfigurationSupport类,自定义JackSon配置。

1.3 特别说明

  • 方案1的模式,在对应变量上加上注解,是可以解决问题,但是严重编码重复,不优雅;
  • 实现WebMvcConfigurer接口与继承WebMvcConfigurationSupport类,是Spring Boot提供开发者做统全局配置类的两种模式,注意两种模式的差异,详情查看后续章节介绍(两种不同的模式,使用不当时,就会出现配置不生效的情况);

自定义Jackson

  1. JackSon配置说明

自定义一个Jackson配置信息,需要了解Jackson的一些配置标准,如:

ContractedBlock.gifExpandedBlockStart.gif

View Code

  1. 实现WebMvcConfigurer接口

重新编写一个ObjectMapper,替换系统默认的bean,就可以实现接口在post请求模式时,对象序列化与反序列化走子定义配置信息了。
重新编写Jackson后,并不能处理get请求时,日期等特殊对象的序列化处理;针对get请求,编写对象的序列化规则函数,通过实现addFormatters()接口,可扩展支持;

编写LocalDateTime转换函数

/**
 * java 8 LocalDateTime转换器
 *
 * @author wangling
 */
public class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public LocalDateTime parse(String text, Locale locale) throws ParseException {
        return LocalDateTime.parse(text, formatter);
    }

    @Override
    public String print(LocalDateTime object, Locale locale) {
        return formatter.format(object);
    }
}

编写LocalDate转换函数

/**
 * java 8 localDate转换器
 *
 * @author wangling
 */
public class LocalDateFormatter implements Formatter<LocalDate> {
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public LocalDate parse(String text, Locale locale) throws ParseException {
        return LocalDate.parse(text, formatter);
    }

    @Override
    public String print(LocalDate object, Locale locale) {
        return formatter.format(object);
    }
}

编写Jackson配置

编写一个自定义的ObjectMapper bean对象,设置优先级替换默认bean。
/**
 * 项目全局配置类
 * 
 * @author wangling
 * @date 2022/06/10
 */
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

  @Override
  public void addFormatters(FormatterRegistry registry) {
    registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
    registry.addFormatterForFieldType(LocalDateTime.class, new LocalDateTimeFormatter());
  }

  @Bean
  @Primary
  public ObjectMapper ObjectMapper() {
    String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    String dateFormat = "yyyy-MM-dd";
    String timeFormat = "HH:mm:ss";
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    // 序列化
    javaTimeModule.addSerializer(
        LocalDateTime.class,
        new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    javaTimeModule.addSerializer(
        LocalDate.class,
        new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat)));
    javaTimeModule.addSerializer(
        LocalTime.class,
        new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat)));
    javaTimeModule.addSerializer(
        Date.class,
        new DateSerializer(false, new SimpleDateFormat(dateTimeFormat)));

    // 反序列化
    javaTimeModule.addDeserializer(
        LocalDateTime.class,
        new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    javaTimeModule.addDeserializer(
        LocalDate.class,
        new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
    javaTimeModule.addDeserializer(
        LocalTime.class,
        new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat)));
    javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
      @SneakyThrows
      @Override
      public Date deserialize(JsonParser jsonParser, DeserializationContext dc) {
        String text = jsonParser.getText().trim();
        SimpleDateFormat sdf = new SimpleDateFormat(dateTimeFormat);
        return sdf.parse(text);
      }
    });
    javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
    javaTimeModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;
  }
}
  1. WebMvcConfigurationSupport类

编写Jackson配置

重新编写Jackson后,并不能处理get请求时,日期等特殊对象的序列化处理;针对get请求,编写对象的序列化规则函数,通过实现addFormatters()接口,可扩展支持;
编写自定义配置Jackson信息时,需要重写extendMessageConverters方法。具体技术细节原因,请参考文档《Spring Boot实现WebMvcConfigurationSupport导致自定义的JSON时间返回格式不生效》

ContractedBlock.gifExpandedBlockStart.gif

View Code

WebMvcConfigurer与WebMvcConfigurationSupport相关知识点

  1. 基础知识点

Spring的 WebMvcConfigurer 接口提供了很多方法让开发者来定制SpringMVC的配置。
WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware。支持的自定义的配置更多更全,WebMvcConfigurerAdapter有的方法,这个类也都有。该类注释内容翻译:这是提供MVC Java config 背后配置的主要类。 通常是通过将@EnableWebMvc添加到应用程序的@Configuration类中来导入的。 另一个更高级的选择是直接从此类扩展并在需要时重写方法,记住子类要添加@Configuration,重写带有@Bean的方法也要加上@Bean。
  1. 使用注意事项

          参考文档:《拦截失效原因》
  1. 实现WebMvcConfigurer: 不会覆盖WebMvcAutoConfiguration的配置
  1. 实现WebMvcConfigurer+注解@EnableWebMvc:会覆盖WebMvcAutoConfiguration的配置
  1. 继承WebMvcConfigurationSupport:会覆盖WebMvcAutoConfiguration的配置
  1. 继承DelegatingWebMvcConfiguration:会覆盖WebMvcAutoConfiguration的配置
  1. 推荐使用模式

  1. 非必要,最好避免WebMvcConfigurer,WebMvcConfigurationSupport在一个项目中同时使用;
  1. 出于安全性拦截配置,建议项目采用WebMvcConfigurer接口的方式做全局配置;
  1. 日期,时间等建议使用LocalDate,替换历史的Date数据类型;

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK