Jackson全局配置和JsonFormat注解设置日期格式

    科技2024-08-10  24

    >>《轻松学习Jackson》教程

    在日常开发中,日期是很常见的一种数据类型,特别是在与数据库打交道的场景。

    为了提升日期的可读性,通常会将日期进行格式化之后再输出,用于前端展示和日志打印等场景。

    Jackson在对日期进行序列化时,也支持按指定的格式进行序列化。

    本篇内容基于Jackson 2.11.2版本,马上开始学习吧。

    默认日期格式

    创建一个代表产品的类Product,其中发布时间publishDate为Date类型。

    public class Product { private String name; private Date publishDate; // 省略getter、setter方法 @Override public String toString() { return "Product [name=" + name + ", publishDate=" + publishDate + "]"; } }

    使用默认的配置进行序列化。

    /** * 默认日期格式化. * * @throws JsonProcessingException */ @Test public void dateToLong() throws JsonProcessingException { Product product = new Product(); product.setName("TV"); product.setPublishDate(new Date()); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(product)); }

    执行结果:

    {"name":"TV","publishDate":1601862136345}

    结果中的publishDate字段值为1601862136345,是一个数字类型。

    在默认情况下,Jackson序列化Date、Calendar日期类型时,会转化为Long数字类型。反序列化时,也是使用Long类型来转化为对应的日期类型。

    全局日期格式化

    Jackson支持设置序列化日期的格式,日期格式参数使用Java的java.text.DateFormat。

    在进行序列化之前,通过调用ObjectMapper的setDateFormat方法,设置指定的日期格式。

    /** * 全局日期格式化. * * @throws JsonProcessingException */ @Test public void dateToString() throws JsonProcessingException { Product product = new Product(); product.setName("TV"); product.setPublishDate(new Date()); ObjectMapper mapper = new ObjectMapper(); // 设置日期格式 mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // mapper.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println(mapper.writeValueAsString(product)); String jsonString = "{\"name\":\"TV\",\"publishDate\":\"2020-10-04 22:21:07\"}"; // 格式化 Product newProduct = mapper.readValue(jsonString, Product.class); System.out.println(newProduct.toString()); jsonString = "{\"name\":\"TV\",\"publishDate\":1601821267709}"; // Long类型 newProduct = mapper.readValue(jsonString, Product.class); System.out.println(newProduct.toString()); }

    执行结果:

    {"name":"TV","publishDate":"2020-10-05 09:57:25"} Product [name=TV, publishDate=Sun Oct 04 22:21:07 CST 2020] Product [name=TV, publishDate=Sun Oct 04 22:21:07 CST 2020]

    序列化后的publishDate字段,值为字符串类型,格式与设置的yyyy-MM-dd HH:mm:ss相同。

    在设置了日期格式之后,反序列化支持2种日期类型,一种是默认的数字类型,另一种是设置的日期格式。

    另外,如果默认的时区不满足要求,可以在设置日期格式的同时,设置对应的时区。

    mapper.setTimeZone(TimeZone.getTimeZone("UTC"));

    其中,getTimeZone的参数为时区ID。例如中国上海为Asia/Shanghai,美国洛杉矶为America/Los_Angeles。

    JsonFormat注解格式化字段

    如果只需要格式化特定的字段,或者不同字段使用不同的格式时,可以使用JsonFormat注解来实现。

    格式化为字符串

    为日期字段添加JsonFormat注解,并指定序列化类型为字符串。

    public class ProductWithJsonFormat { private String name; @JsonFormat(shape=Shape.STRING) private Date publishDate; // 省略getter、setter方法 } /** * 在日期字段添加JsonFormat注解设置日期格式 * * @throws JsonProcessingException */ @Test public void jsonFormat() throws JsonProcessingException { ProductWithJsonFormat product = new ProductWithJsonFormat(); product.setName("TV"); product.setPublishDate(new Date()); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(product)); }

    执行结果:

    {"name":"TV","publishDate":"2020-10-05T04:42:04.842+00:00"}

    指定日期格式

    通过pattern属性指定日期格式为yyyy-MM-dd HH:mm:ss。

    @JsonFormat(shape=Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss") private Date publishDate;

    执行结果:

    {"name":"TV","publishDate":"2020-10-05 04:45:55"}

    指定时区

    格式没问题了,但是时间不对,晚了8个小时。

    JsonFormat注解提供了另外一个属性timezone,用来设置时区,这里设置为中国上海Asia/Shanghai。

    @JsonFormat(shape=Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss", timezone="Asia/Shanghai") private Date publishDate;

    执行结果:

    {"name":"TV","publishDate":"2020-10-05 12:47:20"}

    这个才是我们想要的结果。

    小结

    日期格式化在日常开发中比较常见,常用于前端展示和日志打印等场景,格式化后的可读性比较强。

    对于日期类型,Jackson默认会序列化为数值类型,可读性比较差。

    如果每个日期字段都需要格式化,并且格式都相同,那么可以使用ObjectMapper进行全局的设置。

    如果需要对每个字段单独设置格式,则可以通过JsonFormat注解进行不同的配置。

    同时,需要注意默认的时区是否能够满足需求,时区也可以根据实际需要进行设置。

    参考

    《轻松学习Jackson》程序员口袋里的开发手册

    https://github.com/FasterXML/jackson

    https://www.logicbig.com/tutorials/misc/jackson/json-format.html

    关于我

    公众号:二进制之路

    教程:996geek.com

    博客:binarylife.icu

    Processed: 0.010, SQL: 8