SpringBoot里使用@JsonFormat进行日期json格式化总结

一、概述

在数据传输时,最常使用Json,正常的String转换没啥好讲的,但是日期时间类型的格式有很多,需要转换。本篇文章介绍使用Jackson格式化日期的各种方法,它被Spring Boot用作默认的JSON处理器。

1.1 maven依赖

spring-boot-starter-web默认引入了以下依赖:

二、使用@JsonFormat

2.1 设置格式

我们可以使用 @JsonFormat注释来格式化特定字段:

准备一条测试数据

返回结果

可以看到生日只显到示日期,而创建日期精确到时间。

可以看到,使用@JsonFormat注释格式化特定日期字段非常方便。但是,我们只应在需要字段的特定格式时使用它。如果我们想要在我们的应用程序中使用所有日期的通用格式,那么如何实现这一目标的方式更好,下面会有讲到。

2.2 设置时区

若要使用特定的时区,可以设置@JsonFormat的timezone属性:

北京时间东八区

2.3 配置默认格式

若要为应用程序中的所有日期配置默认格式,可以在application.properties中这样配置:

若在JSON日期中使用特定时区,还有这个属性:

2.4 自定义Jackson的ObjectMapper

就是借助这个类Jackson2ObjectMapperBuilderCustomizer实现

它还有一个优点是适用于Java8和遗留日期类型。

0

Jackson里使用@JsonTypeInfo注解处理多态类型的序列化和反序列化

问题场景

在将多态类型进行JSON序列化后,Jackson无法在反序列化期间找出正确的类型。
可以通过一个例子来理解它。

下面开始序列化和反序列化一个View实例

出现如下错误

使用@JsonTypeInfo

此注解用于序列化有关多态实例的实际类的信息,以便Jackson可以知道要反序列化的子类型。

可以使用以下注释来解决上面出现的异常:

上面的配置指定使用的类名称(use = JsonTypeInfo.Id.CLASS),并将其作为JSON属性保留(include = JsonTypeInfo.As.PROPERTY)。 属性名称应该是’className’。

再次运行我们的main方法:

在上述配置中,元素“ include”和“ property”都是可选的,不写将使用默认值。 默认的“ include”也是JsonTypeInfo.As.PROPERTY,默认的“ property”是@class。

所以,也可以这样写:

将被序列化为:

在属性上使用@JsonTypeInfo

@JsonTypeInfo注释可以在类(上面的示例)和属性上使用。

例如可以在’shapes’属性上使用注解:

如果该注解同时作用在类和属性上,则以使用在属性上的注解为准,因为它被认为更具体。

需要特别说明的是,当@JsonTypeInfo在属性(字段,方法)上使用时,此注解适用于值。 当在集合类型(List,Map,Array)上使用时,它将应用于元素,而不是集合本身。 对于非集合类型,没有区别。

也就是说,在上面的代码中,当我们将其用于“shapes”的list时,它是应用于list里的每个元素(shape),而不是list类型本身。

使用JsonTypeInfo.Id.MINIMAL_CLASS

use = JsonTypeInfo.Id.MINIMAL_CLASS选项将序列化最小的相对程序包路径。

还拿上面的例子来说,如果把use = JsonTypeInfo.Id.CLASS换成use = JsonTypeInfo.Id.MINIMAL_CLASS,那么序列化后的结果是

全局Default Typing机制

除了使用@JsonTypeInfo注解来实现多态数据绑定,还可以使用全局Default Typing机制。

DefaultTyping有四个选项

  • JAVA_LANG_OBJECT: 当对象属性类型为Object时生效
  • OBJECT_AND_NON_CONCRETE: 当对象属性类型为Object或者非具体类型(抽象类和接口)时生效
  • NON_CONCRETE_AND+_ARRAYS: 同上, 另外所有的数组元素的类型都是非具体类型或者对象类型
  • NON_FINAL: 对所有非final类型或者非final类型元素的数组

开启DefaultTyping,并且让所有的非final类型对象持久化时都存储类型信息显然能准确的反序列多态类型的数据。

具体实现,可以看这段代码

在上面的示例中,DefaultTyping.OBJECT_AND_NON_CONCRETE指定默认类型将用于声明类型为java.lang.Object或抽象类型(抽象类或接口,在我们的示例中为Shape)的属性。

请注意,在上面的输出中,List <Shape>的实际类型也作为ArrayList保留。 这是因为List也是non-concrete类型。

pom.xml

0