springboot时间格式化与空值格式化

1 时间格式化

1.1 出参格式化(Json)

创建一个测试类:

@Data
public class TestResponse {
   

    @ApiModelProperty("未格式化时间")
    private LocalDateTime localDateTime;

    @ApiModelProperty("未格式化时间")
    private LocalDate localDate;

    @ApiModelProperty("未格式化时间")
    private Date date;
}

restApi:

 @GetMapping("test")
 @ApiOperation("响应测试")
 public TestResponse test(){
   
      TestResponse response = new TestResponse();
      response.setDate(new Date());
      response.setLocalDateTime(LocalDateTime.now());
      response.setLocalDate(LocalDate.now());
      return response;
  }

响应参数带Time的采用的是“ yyyy-MM-dd’T’HH:mm:ss.SSS ”格式,并且DATE默认使用的是UTC时间,比北京时间慢。
在这里插入图片描述

1.1.1 局部配置

在字段上加上注解@JsonFormat

	@ApiModelProperty("已格式化时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime;


    @ApiModelProperty("已格式化时间")
    @JsonFormat(pattern = "yyyy年MM月dd日")
    private LocalDate localDate;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") //date默认使用UTC时间,北京时间得+8
    @ApiModelProperty("已格式化时间")
    private Date date;

在这里插入图片描述

@JsonFormat是jakson自带注解(spring家族默认使用jakson进行序列化与反序列化),常用属性如下:

属性 作用
pattern 格式化模板,如时间的’yyyy-MM-dd HH:mm:ss
shape 决定数据类型,如NUMBER、ARRAY,默认为ANY,任何类型
locale 语言环境
timezone 时区,默认为UTC

在这里插入图片描述

在JSR310FormattedSerializerBase类createContextual方法中会检查序列化器,首先会获取目标对象字段上的JsonFormat,如果JsonFormat 不为空,会读取其属性值。根据属性值创建DateTimeFormatter对象,并将其设置为序列化器模板。
最终通过HttpMessageConverter接口实现类的子类MappingJackson2HttpMessageConverter输出响应。MappingJackson2HttpMessageConverter为默认的Json转换类。

在这里插入图片描述
也就是更改了LocalDateSerializer、LocalDateTimeSerializer:

在这里插入图片描述

在这里插入图片描述

1.1.2 全局配置

注释掉@JsomFormat:
在这里插入图片描述

1.1.2.1 yml配置文件中进行全局配置
spring:
  jackson:
#    全局配置,但是对LocalDateTime和LocalDate无效
    date-format: yyyy-MM-dd HH:mm:ss
#    时区
    time-zone: GMT+8

重启,可以看到我们在配置文件中设置的格式与时区注入进了ObjectMapper.
在这里插入图片描述
因为未对LocalDateSerializer和LocalDateTimeSerializer进行改动,结果只对date生效。
在这里插入图片描述

1.1.2.2 编写配置类进行全局配置(推荐)

先取消上一步的配置
在这里插入图片描述

手写ObjectMapper配置类:

@Configuration
public class DateTimeConfiguration {
   

 

    @Bean
    public ObjectMapper initObjectMapper(){
    
        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        //JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
        objectMapper.registerModule(new JavaTimeModule());
        return objectMapper;
    }

}

运行结果同之前YML中配置一样:
在这里插入图片描述
所以LocalDateSerializer和LocalDateTimeSerializer中也得按我们需要的格式进行序列化:

 	@Bean
    public ObjectMapper initObjectMapper(){
    //自定义ObjectMapper配置并注册BEAN
        ObjectMapper objectMapper=new ObjectMapper();
        JavaTimeModule javaTimeModule=new JavaTimeModule();
        //针对LocalDateTime和LocalDate
        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        //针对Date类
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        //JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

上面localdate字段未被全局序列化覆盖,因为字段上加了注解,说明局部优先于全局:
在这里插入图片描述
去掉注解:

在这里插入图片描述

在这里插入图片描述
也可以通过Jackson2ObjectMapperBuilder来构建新的ObjectMapper实例设置序列化与反序列化方式:

@Configuration
public class DateTimeConfiguration {
   


 	@Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
    //通过ObjectMapper构造器构建实例
        return builder -> {
   
            builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //date格式,序列化和反序列化都是它
            //序列化
            builder.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
            builder.serializerByType(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
            //反序列化
            builder.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
            builder.deserializerByType(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
        };
    }

 

   //    @Bean
//    public ObjectMapper initObjectMapper(){ //自定义ObjectMapper配置并注册BEAN
//        ObjectMapper objectMapper=new ObjectMapper();
//        JavaTimeModule javaTimeModule=new JavaTimeModule();
//        //针对LocalDateTime和LocalDate
//        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//        //针对Date类
//        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//        //JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
//        objectMapper.registerModule(javaTimeModule);
//        return objectMapper;
//    }

}

1.2 入参格式化

1.2.1 json参数

创建测试接口

	@PostMapping("body")
    @ApiOperation("json请求测试")
    public TestResponse body(@RequestBody TestResponse testResponse){
   
        log.info("打印的body:{}",testResponse);
        return testResponse;
    }

在这里插入图片描述
在这里插入图片描述
因为LocalDateTimeDeserializer与LocalDateDeserializer默认格式模板分别为’yyyy-MM-ddTHH:mm:ss 、'yyyy-MM-dd '.
在这里插入图片描述
在这里插入图片描述
我们按照默认格式传输自然没问题:
在这里插入图片描述
在这里插入图片描述

1.2.1.1 局部配置

同样,我们也可以像局部序列化一样局部反序列化时间。
还是使用@JsonFormat注解(序列化与反序列化一致),此时,标了注解字段全局序列化配置失效:

	@ApiModelProperty("已格式化时间")
    @JsonFormat(pattern = "yyyy年MM月dd日HH时mm分ss秒")
    private LocalDateTime localDateTime;


    @ApiModelProperty("已格式化时间")
    @JsonFormat(pattern = "yyyy年MM月dd日")
    private LocalDate localDate;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS") //date默认使用UTC时间,北京时间得+8
    @ApiModelProperty("已格式化时间")
    private Date date;

同序列化时相同,JSR310DateTimeDeserializerBase反序列化时也是读取注解中的属性值,创建新的JsonDeserializer(包括LocalDateTimeDeserializer、LocalDateDeserializer等)
在这里插入图片描述

1.2.1.2 全局配置

序列化我们用了全局配置,反序列化自然也应该使用全局配置
去掉注解:
在这里插入图片描述
再已有全局配置加上反序列化方式:

	@Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
   
        return builder -> {
   
            builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //date格式,序列化和反序列化都是它
            //序列化
            builder.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
            builder.serializerByType(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
            //反序列化
            builder.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
            builder.deserializerByType(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
        };
    }

在这里插入图片描述
自然也可以自定义并注册ObjectMapper到BEAN

	@Bean
    public ObjectMapper initObjectMapper(){
    //自定义ObjectMapper配置并注册BEAN
        ObjectMapper objectMapper=new ObjectMapper();
        JavaTimeModule javaTimeModule=new JavaTimeModule();
        //针对LocalDateTime和LocalDate
        //序列化
        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        //反序列化
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //针对Date类 序列化和反序列化都是它
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        //JavaTimeModule 是jackson通过jsr310引入的JAVA8格式化类,没有此Module,序列化后的值会比较乱
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

//    @Bean
//    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
   
//        return builder -> {
   
//            builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //date格式,序列化和反序列化都是它
//            //序列化
//            builder.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
//            builder.serializerByType(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
//            //反序列化
//            builder.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒")));
//            builder.deserializerByType(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
//        };
//    }
1.2.2 非json参数

将接口改入参改成非JSON类型

 	@PostMapping("param")
    @ApiOperation("普通参数请求测试")
    public TestResponse body(TestResponse testResponse){
   
        try {
   
            log.info("打印的param:{}",testResponse);
        } catch (Exception e) {
   
            e.printStackTrace();
        }
        return testResponse;
    }
    

在这里插入图片描述

在这里插入图片描述
此时我们配置的json反序列化方式是无效的

1.2.2.1 局部配置

我们再字段上加上注解@DateTimeFormat

	@ApiModelProperty("已格式化时间")
    @DateTimeFormat(pattern = "yyyy年MM月dd日HH时mm分ss秒")
    private LocalDateTime localDateTime;


    @ApiModelProperty("已格式化时间")
    @DateTimeFormat(pattern = "yyyy年MM月dd日")
    private LocalDate localDate;

    @DateT
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值