@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.STRING
或JsonFormat.Shape.NUMBER
,pattern 必须与SimpleDateFormat
兼容- 类级别将作为默认设置,可在属性上覆盖默认行为
Enums
:JsonFormat.Shape.STRING
、JsonFormat.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#shape
为 JsonFormat.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}