@JsonFormat 格式化时间、枚举

@JsonFormat是通用注释,可用于将特定类型序列化为特定格式。

用于配置如何序列化属性值的详细信息。与大多数其他 Jackson 注释不同,它没有特定的通用解释,相反,它的效果取决于被注释属性的数据类型。

常见的用途是选择不同的显示格式。例如,java.util.date 是要序列化为数字(Java时间戳)还是字符串(例如ISO-8601兼容的时间值)——以及使用 pattern 属性配置更详细的细节。

package com.fasterxml.jackson.annotation;
 ...
public @interface JsonFormat{
    ...
    // 特定于数据类型的附加配置,可用于进一步细化格式化方面。例如,可以指定Date的格式为 "yyyy-MM-dd"
    public String pattern() default "";
    
    // 用于序列化的结构:映射的定义依赖于数据类型,但通常有直接对应的数据格式(JSON)。比如序列化为字符串、数字、对象等等
    public Shape shape() default Shape.ANY;
    
    // java.util.Locale to use for serialization (if needed)
    public String locale() default DEFAULT_LOCALE;
    
    // java.util.TimeZone to use for serialization (if needed)。可解决相差 8 小时的问题
    public String timezone() default DEFAULT_TIMEZONE;
    
    //whether "lenient" handling should be enabled. 
    //This is relevant mostly for deserialization of some textual
    // datatypes, especially date/time types
    public OptBoolean lenient() default OptBoolean.DEFAULT;

    // 启用 JsonFormat.Feature 功能
    public JsonFormat.Feature[] with() default { };

    // 禁用 JsonFormat.Feature 功能
    public JsonFormat.Feature[] without() default { };
   ....
}

截至 Jackson 2.6,已知的特殊处理:

  • java.util.Date:shape 可以是 JsonFormat.Shape.STRINGJsonFormat.Shape.NUMBER,pattern 必须与 SimpleDateFormat 兼容
  • 类级别将作为默认设置,可在属性上覆盖默认行为
  • EnumsJsonFormat.Shape.STRINGJsonFormat.Shape.NUMBER 将分别使用 ordinals、name 进行序列化,也可以用 JsonFormat.Shape.OBJECT 将枚举序列化为 JSON 对象,只能用在类级别上,不能用在属性上
  • java.util.Collection:可使用 JsonFormat.Shape.OBJECT 序列化为 JSON 对象而不是数组,只能用在类级别上,不能用在属性上
  • Number:子类能使用 JsonFormat.Shape.OBJECT 序列化为完整的对象。否则默认行为是序列化为标量值(scalar number value)。只能用在类级别上,不能用在属性上

格式化时间

默认 Date/Calendar 会被序列化为毫秒数。为了序列化为字符串,需要指定 @JsonFormat#shapeJsonFormat.Shape.STRING,且用 @JsonFormat#pattern 指定 兼容SimpleDateFormat 的格式。也可以选择性的指定 @JsonFormat#timezone@JsonFormat#locale。例如:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss Z", timezone="America/New_York")
private Date startDate;

格式化枚举

默认枚举会被序列化为它们的 name,为了以序号的形式序列化,需要使用 JsonFormat.Shape.NUMBER

@JsonFormat(shape = JsonFormat.Shape.NUMBER)
private Dept dept;

Example

Java Object

public class Employee {
    private String name;
    @JsonFormat(shape = JsonFormat.Shape.STRING, timezone = "Asia/Shanghai")
    private Date dateOfBirth;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss Z", timezone = "Asia/Shanghai")
    private Date startDate;
    @JsonFormat(shape = JsonFormat.Shape.NUMBER)
    private Dept dept;
    ...
}    
public class ExampleMain {
    public static void main(String[] args) throws IOException {
        Employee employee = new Employee();
        employee.setName("Amy");
        employee.setDateOfBirth(Date.from(ZonedDateTime.now().minusYears(30).toInstant()));
        employee.setStartDate(Date.from(ZonedDateTime.now().minusYears(2).toInstant()));
        employee.setDept(Dept.Sales);

        System.out.println("-- before serialization --");
        System.out.println(employee);

        System.out.println("-- after serialization --");
        ObjectMapper om = new ObjectMapper();
        String jsonString = om.writeValueAsString(employee);
        System.out.println(jsonString);

        System.out.println("-- after deserialization --");
        System.out.println(om.readValue(jsonString, Employee.class));
    }
}
-- before serialization --
Employee{name='Amy', dateOfBirth=Sun Apr 21 21:26:07 CDT 1991, startDate=Sun Apr 21 21:26:07 CST 2019, dept=Sales}
-- after serialization --
{"name":"Amy","dateOfBirth":"1991-04-21T21:26:07.681+09:00","startDate":"2019-04-21 21:26:07 +0800","dept":2}
-- after deserialization --
Employee{name='Amy', dateOfBirth=Sun Apr 21 21:26:07 CDT 1991, startDate=Sun Apr 21 21:26:07 CST 2019, dept=Sales}

不使用 timezone

public class Employee {
    private String name;
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Date dateOfBirth;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss Z")
    private Date startDate;
    @JsonFormat(shape = JsonFormat.Shape.NUMBER)
    private Dept dept;
    ...
}    

before serialization 与 after serialization 的时间相差了 21 - 13 = 8 小时。

-- before serialization --
Employee{name='Amy', dateOfBirth=Sun Apr 21 21:25:02 CDT 1991, startDate=Sun Apr 21 21:25:02 CST 2019, dept=Sales}
-- after serialization --
{"name":"Amy","dateOfBirth":"1991-04-21T12:25:02.627+00:00","startDate":"2019-04-21 13:25:02 +0000","dept":2}
-- after deserialization --
Employee{name='Amy', dateOfBirth=Sun Apr 21 21:25:02 CDT 1991, startDate=Sun Apr 21 21:25:02 CST 2019, dept=Sales}

不使用@JsonFormat

时间被序列化为毫秒数,枚举被序列化为 name

-- before serialization --
Employee{name='Amy', dateOfBirth=Sun Apr 21 21:19:52 CDT 1991, startDate=Sun Apr 21 21:19:52 CST 2019, dept=Sales}
-- after serialization --
{"name":"Amy","dateOfBirth":672236392972,"startDate":1555852792973,"dept":"Sales"}
-- after deserialization --
Employee{name='Amy', dateOfBirth=Sun Apr 21 21:19:52 CDT 1991, startDate=Sun Apr 21 21:19:52 CST 2019, dept=Sales}

原文链接

Jackson JSON - Using @JsonFormat to format Date and Enum

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值