开发者

详解SpringBoot中时间类型的序列化与反序列化

开发者 https://www.devze.com 2023-02-02 10:44 出处:网络 作者: 我妻礼弥
目录背景约定反序列化局部处理反序列化全局处理序列化局部处理全局处理推荐配置背景
目录
  • 背景
  • 约定
  • 反序列化
    • 局部处理反序列化
    • 全局处理
  • 序列化
    • 局部处理
    • 全局处理
  • 推荐配置

    背景

    前后端进行时间类型的传递时,往往是

    • 前端传递时间格式的字符串,后端反序列化成对应的时间类型
    • 后端返回数据时,一般是将时间类型的对象,序列化成时间格式的字符串

    Spring 的生态中已经为我们提供了对应的解决方案

    约定

    如下是对本文的讨论背景做出的约定

    • 框架 : Spring boot (Spring web)
    • json 序列化、反序列化工具 : Jackson
    • 传输协议 : http
    • 接口返回值格式 : JSON

    反序列化

    时间格式字符串->时间类型

    常见于前端传参,一般分为4种情况

    • Post + Content-Type : application/json
    • Post + Content-Type : application/x-www-form-urlencoded
    • Post + Content-Type : multipart/form-data
    • Get

    以上四种最常见情况,每种数据编码格式都不一样,因此对应的反序列化方法也不同

    Spring web 生态中,对于 Post + Content-Type : application/json 的方式 一般是用 json 工具进行反序列化,例如 Spring 自带的 jackson,抑或是阿里巴巴的 fastjson

    而其它非 json 提交的情况, json 工具就派不上用场了,Spring 提供了额外的反序列化方式,来处理这些情况

    局部处理反序列化

    局部处理反序列化的好处在于,粒度更细,使用更灵活,在 Spring web 生态中有两种局部处理方式,来处理上述4种常见情况

    @JsonFormat 或 @JSONField

    @JsonFormat@JSONField 注解都可以用在时间类型的字段上,用来对该字段提供反序列化支持,例如

    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date date;
    
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime4;
    
    @JSONField(format="yyyy-MM-dd")
    private LocalDate localDate;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date date;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime4;
    
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate localDate;
    

    注意 @JsonFormat@JSONField 注解,只能用于json(Post + Content-Type : application/json)提交的反序列化,表单提交或者Get提交是不支持的

    // 这种带 @RequestBody 的 Pojo ,内部的 时间类型字段就可以使用  @JsonFormat 或 @JSONField
    @PostMapping("/json")
    public Pojo json(@RequestBody Pojo pojo) {
        return pojo;
    }
    

    @JsonFormat@JSONField 的区别与使用@JsonFormat 注解来源于 Spring web 自带 jackson,无需配置直接可以使用

    @JSONField 注解来源于阿里巴巴的 fastjson,需要进行配置,用 fastjson 替换掉Spring web 默认使用的 jackson 之后,才能使用。

    @DateTimeFormat

    @DateTimeFormatSpring web 提供的针对非 json 提交,如

    • Post + Content-Type : application/x-www-form-urlencoded
    • Post + Content-Type : multipart/form-data
    • Get

    等方式时,时间类型的反序列化解决方案

    // Get 传参的 Pjsojo ,内部的 时间类型字段可以使用 @DateTimeFormat 进行反序列化
    @GetMapping
    public Pojo get(Pojo pojo) {
        return pojo;
    }
    
    // 表单传参的 Pojo ,内部的 时间类型字段可以使用 @DateTimeFormat 进行反序列化
    @PostMapping
    public Pojo post(Pojo pojo) {
        return pojo;
    }

    @DateTimeFormat 的用法

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date date;
    
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime;
    
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate localDate;
    

    全局处理

    Spring web 对于 json 传参 使用的是 HttpMessageConverter<T> 转换类,而时间字符串作为普通请求参数传入时,转换用的是 Converter<S, T>, Converter 的不同,意味着处理方式也不同。

    非 json 传参的反序列化全局处理

    import org.apache.commons.lang3.StringUtils;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.convert.converter.Converter;
    
    import Java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.time.*;
    import java.time.format.DateTimeFormatter;
    import java.util.Date;
    import java.util.TimeZone;
    
    /**
     * 自定义参数转换器,全局反序列化 GET请求、POST表单 提交的时间字符串
     */
    @Configuration
    public class DateConverterConfig {
    
        /**
         * yyyy-MM-dd 时间格式的正则表达式
         */
        private static final String DATE_REGEX = "[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])";
    
        /**
         * HH:mm:ss 时间格式的正则表达式
         */
        private static final String TIME_REGEX = "(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d";
    
        /**
         * yyyy-MM-dd HH:mm:ss 时间格式的正则表达式
         */
        private static final String DATE_TIME_REGEX = DATE_REGEX + "\s" + TIME_REGEX;
    
        /**
         * yyyy-MM-ddTHH:mm:ss 时间格式的正则表达式
         */
        private static final String DATE_T_TIME_REGEX = DATE_REGEX + "T" + TIME_REGEX;
    
        /**
         * yyyy-MM-ddTHH:mm:ss.SSS 时间格式的正则表达式
         */
        private static final String DATE_T_TIME_MS_REGEX = DATE_REGEX + "T" + TIME_REGEX + ".\d{3}";
    
        /**
         * 13位时间戳正则表达式
         */
        private static final String TIME_STAMP_REGEX = "1\d{12}";
    
        /**
         * yyyy-MM 时间格式的正则表达式
         */
        private static final String YEAR_MONTH_REGEX = "[1-9]\d{3}-(0[1-9]|1[0-2])";
    
        /**
         * yyyy-MM 格式
         */
        private static final String YEAR_MONTH_PATTERN = "yyyy-MM";
    
        /**
         * DateTime格式化字符串
         */
        private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
        /**
         * DateTime格式化字符串 ISO 格式
         */
        private static final String DEFAULT_DATETIME_ISO_PATTERN = "yyyy-MM-ddTHH:mm:ss";
    
        /**
         * DateTime格式化字符串 带毫秒值的 ISO 格式
         */
        private static final String DEFAULT_DATETIME_MS_ISO_PATTERN = "yyyy-MM-ddTHH:mm:ss.SSS";
    
        /**
         * Date格式化字符串
         */
        private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    
        /**
         * Time格式化字符串
         */
        private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
    
        /**
         * 根据 pattern 构建 SimpleDateFormat
         * @param pattern
         * @return
         */
        private SimpleDateFormat getSimpleDateFormat(String pattern){
            SimpleDateFormat df =  new SimpleDateFormat(pattern);
            System.out.println(TimeZone.getDefault());
            df.setTimeZone(TimeZone.getTimeZone ("GMT"));
            return df;
        }
    
        /**
         * String -> Date 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, Date> dateConverter() {
            return new Converter<String, Date>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public Date convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // 13位毫秒值 -> Date
                    if (source.matches(TIME_STAMP_REGEX)) {
                        return new Date(Long.parseLong(source));
                    }
                    try {
                        // yyyy-MM-dd HH:mm:ss -> Date
                        if (source.matches(DATE_TIME_REGEX)) {
                            return getSimpleDateFormat(DEFAULT_DATETIME_PATTERN).parse(source);
                        }
    
                        // yyyy-MM-dd -> Date
                        if (source.matches(DATE_REGEX)) {
                            return getSimpleDateFormat(DEFAULT_DATE_FORMAT).parse(source);
                        }
    
                        // yyyy-MM -> Date
                        if (source.matches(YEAR_MONTH_REGEX)) {
                            return getSimpleDateFormat(YEAR_MONTH_PATTERN).parse(source);
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                    return null;
                }
            };
        }
    
    
        /**
         * String -> LocalDateTime 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, LocalDateTime> localDateTimeConverter() {
            return new Converter<String, LocalDateTime>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public LocalDateTime convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // 13位毫秒值 -> LocalDateTime
                    if (source.matches(TIME_STAMP_REGEX)) {
                        Instant instant = Instant.ofEpochMilli(Long.parseLong(source));
                        ZoneId zone = ZoneId.systemDefault();
                        return LocalDateTime.ofInstant(instant, zone);
                    }
                    // yyyy-MM-dd HH:mm:ss -> LocalDateTime
                    if (source.matches(DATE_TIME_REGEX)) {
                        return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN));
                    }
    
                    // yyyy-MM-ddTHH:mm:ss -> LocalDateTime
                    if (source.matches(DATE_T_TIME_REGEX)) {
                        return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_ISO_PATTERN));
                    }
    
                    // yyyy-MM-ddTHH:mm:ss.SSS -> LocalDateTime
                    if (source.matches(DATE_T_TIME_MS_REGEX)) {
                        return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_MS_ISO_PATTERN));
                    }
    
                    return null;
                }
            };
        }
    
        /**
         * String -> LocalDate 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, LocalDate> localDateConverter() {
            return new Converter<String, LocalDate>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public LocalDate convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // 13位毫秒值 -> LocalDate
                    if (source.matches(TIME_STAMP_REGEX)) {
                        Instant instant = Instant.ofEpochMilli(Long.parseLong(source));
                        ZoneId zone = ZoneId.systemDefault();
                        return LocalDateTime.ofInstant(instant, zone).toLocalDate();
                    }
    
                    // yyyy-MM-dd -> LocalDate
                    if (source.matches(DATE_REGEX)) {
                        return LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
                    }
    
                    return null;
                }
            };
        }
    
        /**
         * String -> LocalTime 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, LocalTime> localTimeConverter() {
            return new Converter<String, LocalTime>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public LocalTime convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // HH:mm:ss -> LocalTime
                    return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT));
                }
            };
        }
    
    }

    注意:使用了自定义参数转化器(Converter),Spring 会优先使用该方式进行处理,@DateTimeFormat 注解将不生效!!! 这两种方案是不兼容!!!

    json 传参的反序列化全局处理

    如果是 json 传参,反序列化时,可以通过配置 json 工具进行全局处理。

    Spring web 自带的 jackson 为例,它配置全局时间格式化时, java.util 包中的时间类型与 java 8 之后引入了 java.time 包中的时间类型,要分开配置

    全局配置 java.util 包中的时间类型的反序列化格式

    常用的时间类型包括

    • java.utijsl.Date
    • java.util.Calendar

    通过配置文件配置,以 yaml 为例

    spring:
      jackson:
        date-format: yyyy-MM-dd HH:mm:ss
        time-zone: GMT+8
    

    这是最简单的配置方式,也可以采取其他方式,这里就不例举了

    全局配置 java.time 包中的时间类型的反序列化格式

    常用的时间类型包括

    • java.time.LocalDateTime
    • java.time.LocalDate
    @Configuration
    public class JacksonConfig {
        private static final String DATE_FORMAT = "yyyy-MM-dd";
        private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
        
        @Bean
        public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
            return builder -> {
                builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
                builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT)));
            };
        }
    }

    序列化

    时间类型->时间格式字符串

    常见于后端返回,现在后端接口,返回格式一般都采用 json ,因此处理起来比反序列化要简单

    局部处理

    在要返回类的时间类型字段上使用 @JsonFormat@JSONField 注解,来对该字段提供序列化支持。例如

    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date date;
    
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime4;
    
    @JSONField(format="yyyy-MM-dd")
    private LocalDate localDate;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date date;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime4;
    
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate localDate;
    

    是的 @JsonFormat@JSONField 注解,既能用于json提交的反序列化,也能用于返回 json 的序列化

    同样,使用 @JSONField 注解之前,需要先进行配置。用 fastjson 替换掉Spring web 默认使用的 jackson 之后,才能使用。

    全局处理

    Spring web 自带的 jackson 为例,它配置全局时间格式化时, java.util 包中的时间类型与 java 8 之后引入了 java.time 包中的时间类型,要分开配置

    全局配置 java.util 包中的时间类型的序列化格式

    常用的时间类型包括

    • java.util.Date
    • java.util.Calendar

    通过配置文件配置

    以 yaml 为例

    spring:
      jackson:
        date-format: yyyy-MM-dd HH:mm:ss
        time-zone: GMT+8
    

    这是最简单的配置方式,也可以采取其他方式,这里就不例举了

    全局配置 java.time 包中的时间类型的序列化格式

    常用的时间类型包括

    • java.time.LocalDateTime
    • java.time.LocalDate
    @Configuration
    public class JacksonConfig {
        private static final String DATE_FORMAT = "yyyy-MM-dd";
        private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
        @Bean
        public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
            return jacksonObjectMapperBuilder -> {
                // 配置 Jackson 序列化 LocalDate、LocalDateTime 时使用的格式
                jacksonObjectMapperBuilder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)));
                jacksonObjectMapperBuilder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
            };
        }
    }

    推荐配置

    对时间类型进行 序列化 时, 由于统一返回的都是 json 格式,推荐进行全局配置,实际开发过程中,如果遇到特php殊情况,再选择用 @JsonFormat 进行局部覆盖

    对时间类型进行 反序列化

    • 如果是 json 传参同样推荐全局配置,实际开发过程中,如果遇到特殊情况,再选择用 @JsonFormat 进行局部覆盖。
    • 如果是 Get 请求或是 Post表单,全局配置 Converter<S, T> 后,@DateTimeForma 注解将失效。看情况自行选择。

    配置一览

    spring:
      jackson:
        date-format: yyyy-MM-dd HH:mm:ss
        time-zone: GMT+8
    
    @Configuration
    public class JacksonConfig {
        private static final String DATE_FORMAT = "yyyy-MM-dd";
        private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
        @Bean
        public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
            return jacksonObjectMapperBuilder -> {
                // 配置 Jackson 序列化 LocalDate、LocalDateTime 时使用的格式
                jacksonObjectMapperBuilder.serializers(new L开发者_自学开发ocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)));
                jacksonObjectMapperBuilder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
                // 配置 Jackson 反序列化 LocalDate、LocalDateTime 时使用的格式
                jacksonObjectMapperBuilder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
                jacksonObjectMapperBuilder.deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT)));
            };
        }
    }
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.time.*;
    import java.time.format.DateTimeFormatter;
    import java.util.Date;
    import java.util.TimeZone;
    
    /**
     * 自定义参数转换器,全局反序列化 GET请求、POST表单 提交的时间字符串
     */
    @Configuration
    public class DateConverterConfig {
    
        /**
         * yyyy-MM-dd 时间格式的正则表达式
         */
        private static final String DATE_REGEX = "[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])";
    
        /**
         * HH:mm:ss 时间格式的正则表达式
         */
        private static final String TIME_REGEX = "(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d";
    
        /**
         * yyyy-MM-dd HH:mm:ss 时间格式的正则表达式
         */
        private static final String DATE_TIME_REGEX = DATE_REGEX + "\s" + TIME_REGEX;
    
        /**
         * yyyy-MM-ddTHH:mm:ss 时间格式的正则表达式
         */
        private static final String DATE_T_TIME_REGEX = DATE_REGEX + "T" + TIME_REGEX;
    
        /**
         * yyyy-MM-ddTHH:mm:ss.SSS 时间格式的正则表达式
         */
        private static final String DATE_T_TIME_MS_REGEX = DATE_REGEX + "T" + TIME_REGEX + ".\d{3}";
    
        /**
         * 13位时间戳正则表达式
         */
        private static final String TIME_STAMP_REGEX = "1\d{12}";
    
        /**
         * yyyy-MM 时间格式的正则表达式
         */
        private static final String YEAR_MONTH_REGEX = "[1-9]\d{3}-(0[1-9]|1[0-2])";
    
        /**
         * yyyy-MM 格式
         */
        private static final String YEAR_MONTH_PATTERN = "yyyy-MM";
    
        /**
         * DateTime格式化字符串
         */
        private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
        /**
         * DateTime格式化字符串 ISO 格式
         */
        private static final String DEFAULT_DATETIME_ISO_PATTERN = "yyyy-MM-ddTHH:mm:ss";
    
        /**
         * DateTimephp格式化字符串 带毫秒值的 ISO 格式
         */
        private static final String DEFAULT_DATETIME_MS_ISO_PATTERN = "yyyy-MM-ddTHH:mm:ss.SSS";
    
        /**
         * Date格式化字符串
         */
        private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    
        /**
         * Time格式化字符串
         */
        private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
    
        /**
         * 根据 pattern 构建 SimpleDateFormat
         * @param pattern
         * @return
         */
        private SimpleDateFormat getSimpleDateFormat(String pattern){
            SimpleDateFormat df =  new SimpleDateFormat(pattern);
            System.out.println(TimeZone.getDefault());
            df.setTimeZone(TimeZone.getTimeZone ("GMT"));
            return df;
        }
    
        /**
         * String -> Date 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, Date> dateConverter() {
            return new Converter<String, Date>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public Date convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // 13位毫秒值 -> Date
                    if (source.matches(TIME_STAMP_REGEX)) {
                        return new Date(Long.parseLong(source));
                    }
                    try {
                        // yyyy-MM-dd HH:mm:ss -> Date
                        if (source.matches(DATE_TIME_REGEX)) {
                            return getSimpleDateFormat(DEFAULT_DATETIME_PATTERN).parse(source);
                        }
    
                        // yyyy-MM-dd -> Date
                        if (source.matches(DATE_REGEX)) {
                            return getSimpleDateFormat(DEFAULT_DATE_FORMAT).parse(source);
                        }
    
                        // yyyy-MM -> Date
                        if (source.matches(YEAR_MONTH_REGEX)) {
                            return getSimpleDateFormat(YEAR_MONTH_PATTERN).parse(source);
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                    return null;
                }
            };
        }
    
    
        /**
         * String -> LocalDateTime 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, LocalDateTime> localDateTimeConverter() {
            return new Converter<String, LocalDateTime>() {
                @SuppressWarnings("pythonNullableProblems")
                @Override
                public LocalDateTime convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // 13位毫秒值 -> LocalDateTime
                    if (source.matches(TIME_STAMP_REGEX)) {
                        Instant instant = Instant.ofEpochMilli(Long.parseLong(source));
                        ZoneId zone = ZoneId.systemDefault();
                        return LocalDateTime.ofInstant(instant, zone);
                    }
                    // yyyy-MM-dd HH:mm:ss -> LocalDateTime
                    if (source.matches(DATE_TIME_REGEX)) {
                        return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN));
                    }
    
                    // yyyy-MM-ddTHH:mm:ss -> LocalDateTime
                    if (source.matches(DATE_T_TIME_REGEX)) {
                        return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_ISO_PATTERN));
                    }
    
                    // yyyy-MM-ddTHH:mm:ss.SSS -> LocalDateTime
                    if (source.matches(DATE_T_TIME_MS_REGEX)) {
                        return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATETIME_MS_ISO_PATTERN));
                    }
    
                    return null;
                }
            };
        }
    
        /**
         * String -> LocalDate 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, LocalDate> localDateConverter() {
            return new Converter<String, LocalDate>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public LocalDate convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // 13位毫秒值 -> LocalDate
                    if (source.matches(TIME_STAMP_REGEX)) {
                        Instant instant = Instant.ofEpochMilli(Long.parseLong(source));
                        ZoneId zone = ZoneId.systemDefault();
                        return LocalDateTime.ofInstant(instant, zone).toLocalDate();
                    }
    
                    // yyyy-MM-dd -> LocalDate
                    if (source.matches(DATE_REGEX)) {
                        return LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
                    }
    
                    return null;
                }
            };
        }
    
        /**
         * String -> LocalTime 转换器
         * 用于转换 @RequestParam参数、@PathVariable参数、表单参数
         */
        @Bean
        public Converter<String, LocalTime> localTimeConverter() {
            return new Converter<String, LocalTime>() {
                @SuppressWarnings("NullableProblems")
                @Override
                public LocalTime convert(String source) {
                    if (StringUtils.isEmpty(source)) {
                        return null;
                    }
                    // HH:mm:ss -> LocalTime
                    return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT));
                }
            };
        }
    
    }

    以上就是详解SpringBoot中时间类型的序列化与反序列化的详细内容,更多关于SpringBoot序列化 反序列化的资料请关注我们其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号