优雅的返回json数据之Jackson常用注解介绍
一、Jackson简介
1. Jackson可以用来干嘛?
Jackson 是一个能够将java对象序列化为JSON字符串,也能够将JSON字符串反序列化为java对象的框架。
2. Json解析器
Jackson提供了两种不同的JSON解析器:
- ObjectMapper: 把JSON解析到自定义的Java类中,或者解析到一个Jackson指定的树形结构中(Tree model);
- Jackson JsonParser: 一种“拉式”(pull)解析器,每次解析一组JSON数据。
3. Json生成器
Jackson也包含了两种不同的JSON生成器:
- ObjectMapper: 把自定义的Java类,或者一个Jackson指定的树形结构生成为JSON文件;
- Jackson JsonGenerator: 每次只生成一组JSON数据。
二、Jackson常用注解
1. 序列化/反序列化时忽略特定属性
在很多场景里,我们并不希望将Java对象的所有属性都序列化。举个例子,我们有一个User实体类,里面有username、password等字段,为了增强安全性,在返回的json数据中肯定是不能包含password属性的。
(1)@JsonIgnoreProperties
@JsonIgnoreProperties
是类级别的注解,写在需要序列化 / 反序列化的类上,用来列出要忽略的属性,或表示将忽略任何未知的属性。
- 序列化时,
@JsonIgnoreProperties({"prop1", "prop2"})
表示忽略Java类里的prop1、prop2对象; - 反序列化时,
@JsonIgnoreProperties(ignoreUnknown=true)
表示忽略没有 Getter / Setter方法的属性。
@JsonIgnoreProperties
还可以配合allowGetters,allowSetters一起用,用来控制是在序列化还是反序列化的时候才忽略属性,这样更加灵活,如:
-
@JsonIgnoreProperties(value = {"prop1", "prop2"},allowGetters = true)
表示属性允许序列化,反序列的时候忽略该属性; -
@JsonIgnoreProperties(value = {"prop1", "prop2"},allowSetters = true)
允许属性反序列化,序列化的时候忽略该属性。
(2)@JsonIgnore
@JsonIgore
注解是方法级别的注解,写在类属性上或类属性的 Getter / Setter方法上,用于忽略指定属性的序列化与反序列化。
- 仅需要将该注解添加到 属性名、属性的getter / setter方法 三者中的其中一个上面。
@JsonIgore
注解会影响“ 整个”属性:也就是说,向“ getter”方法中添加注解也将禁用“ setter”方法。 - 如果需要控制到更小粒度,我们可以用
@JsonProperty
注解来控制是在序列化还是反序列化的时候才忽略属性。 比如,在属性的getter方法上写@JsonIgnore
注解,“ setter”方法上写@JsonProperty
注解,表示允许属性反序列化,序列化的时候忽略该属性。
(3)@JsonIgnoreType
@JsonIgnoreType
是类级别的注解,写在Java类上,表明在序列化和反序列化的时候忽略这个类 。
(4)@JsonInclude
@JsonInclude
注解用于定义序列化时是否不应包含某些“non-values ” (nulls or empty values);可以按属性使用,也可以作为类的默认值使用(用于类的所有属性)。有以下几种策略:
-
@JsonInclude(value = JsonInclude.Include.ALWAYS)
,默认策略,表示任何情况下都序列化该字段,和不写这个注解是一样的效果。 -
@JsonInclude(value = JsonInclude.Include.NON_NULL)
,最常用策略,表示如果加该注解的字段为null,那么就不序列化这个字段了。 - …
2.序列化/反序列化时格式化日期属性
@JsonFormat
注解用于指定序列化日期/时间值(Date/Time)时要使用的格式。
(1)格式化Date
首先我这里写个实体类,getter和setter方法没有贴出来:
public class Param {
private Date date;
}
这是这个实体类序列化后的json数据格式显示 :
{
"date": "2019-04-28T08:18:21.554+0000"
}
对实体类稍微修饰了一下,加上了格式转换 :
public class Param {
@JsonFormat(shape = JsonFormat.Shape.STRING , pattern = "yyyy-MM-dd HH:mm:ss")
private Date date;
}
现在序列化后的json数据长下面这样:
{
"date": "2019-04-28 08:24:14"
}
(2)返回毫秒数
还是同一个实体类,此时指定shape为 JsonFormat.Shape.NUMBER
类型,返回的是毫秒数。
public class Param {
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
private Date date;
}
序列化后的json数据长下面这样:
{
"date": 1556440065032
}
(3)指定时区
public class Param {
@JsonFormat(shape = JsonFormat.Shape.STRING , pattern = "yyyy-MM-dd HH:mm:ss", , timezone = "UTC")
private Date date;
}
{
"date": "2019-04-28 08:30:47"
}
我测试的时候每次返回的都是现在的时间,但是现在的时间是16点多,但是一直显示的是早上八点多,所以我看了下里面的代码,发现用了这个注解以后默认的时区就是UTC,所以用这个注解的时候要进行时区转换。
/**
* {@link java.util.TimeZone} to use for serialization (if needed).
* Special value of {@link #DEFAULT_TIMEZONE}
* can be used to mean "just use the default", where default is specified
* by the serialization context, which in turn defaults to system
* default (UTC) unless explicitly set to another timezone.
*/
public String timezone() default DEFAULT_TIMEZONE;
将时区重新设置成Asia/Shanghai
public class Param {
@JsonFormat(shape = JsonFormat.Shape.STRING , pattern = "yyyy-MM-dd HH:mm:ss", , timezone = "Asia/Shanghai")
private Date date;
}
现在时间就是咱们的北京时间了,16点多。
{
"date": "2019-04-28 16:45:22"
}