详解jackson注解(三)jackson包含属性、忽略属性的注
2019-12-07 本文已影响0人
chushiyan
详解jackson注解(三)jackson包含属性、忽略属性的注解
jackson中,指定包含哪些属性、忽略哪些属性的注解:
注解类 | 描述 | |
---|---|---|
1 | JsonIgnoreProperties | 用于标记忽略一个或多个属性。可以注解在类上、构造函数、方法、字段上。 |
2 | JsonIgnore | @JsonIgnore注解用于在字段级别标记要忽略的属性。注意:系列化和反系列化时都会被忽略。 |
3 | JsonInclude | 使用@JsonInclude可以只包含非空的属性,也即排除值为empty、null的属性。 |
4 | JsonAutoDetect | 默认情况下,jackson获取public权限的字段进行系列化和反系列化。如果没有public修饰的字段,就会去获取public修饰的getter/setter。使用 JsonAutoDetect注解,我们就可以修改默认的行为。 |
一、JsonIgnoreProperties
用于标记忽略一个或多个属性。可以注解在类上、构造函数、方法、字段上。
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* @author chushiyan
* @email chushiyan0415@163.com
* @description 自关联的权限表。一个权限有一个父权限、多个子权限
*/
@Data
public class Permission implements Serializable {
private String id;
private String name;
@ManyToOne
@JoinColumn(name = "permission_parent_id", referencedColumnName = "permission_id")
private Permission parent;
// 必须使用JsonIgnoreProperties忽略parent属性
// 否则查询到子权限,子权限有parent属性,又去查父权限,会导致系列化时出现死循环
@JsonIgnoreProperties(value = "parent")
@OneToMany(mappedBy = "parent")
private Set<Permission> children = new HashSet<Permission>();
}
二、JsonIgnore
@JsonIgnore注解用于在字段级别标记要忽略的属性。注意:系列化和反系列化时都会被忽略。
1、bean
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.io.Serializable;
/**
* @author chushiyan
* @email chushiyan0415@163.com
* @description
*/
@Data
public class Article implements Serializable {
private String id;
private String name;
@JsonIgnore
private String category;
}
2、测试
@Test
public void testJsonIgnore() throws JsonProcessingException {
String json = "{"
+ "\"id\" : \"100\","
+ "\"name\" : \"详解jackson注解","
+ "\"category\" : \"jackson\""
+ "}";
ObjectMapper mapper = new ObjectMapper();
Article article = mapper.readValue(json,Article.class);
System.out.println(article);
Article article2 = new Article();
article2.setId("100");
article2.setName("详解jackson注解");
article2.setCategory("jackson");
String json2 = mapper.writeValueAsString(article2);
System.out.println(json2);
}
3、控制台输出
Article(id=100, name=详解jackson注解, category=null)
{"id":"100","name":"详解jackson注解"}
反系列化时,json数据中明明包含了category值,但是最后Article对象的category属性值依然为null。就是因为使用了JsonIgnore。
三、JsonInclude
我们可以使用@JsonInclude排除某些empty、null、默认值的属性。
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* @author chushiyan
* @email chushiyan0415@163.com
* @description
*/
// 使用JsonInclude注解指明只包含非null的属性,即排除值为null的属性
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result {
private boolean flag;// 是否成功
private Integer code;// 返回码
private String message;// 返回信息
private Object data;// 返回数据
public Result() {
}
public Result(boolean flag, Integer code, String message) {
this.flag = flag;
this.code = code;
this.message = message;
}
public Result(boolean flag, Integer code, String message, Object data) {
this.flag = flag;
this.code = code;
this.message = message;
this.data = data;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return "Result{" +
"flag=" + flag +
", code=" + code +
", message='" + message + '\'' +
", data=" + data +
'}';
}
}
2、controller
@GetMapping("/test8")
public Result testJsonInclude(){
return new Result(true,200,"查询成功");
}
没有在Result类上加 @JsonInclude(JsonInclude.Include.NON_NULL) 注解时,返回的响应:
{
"flag": true,
"code": 200,
"message": "查询成功",
"data": null
}
加了之后的返回的响应:
{
"flag": true,
"code": 200,
"message": "查询成功"
}
四、 JsonAutoDetect
默认情况下,jackson获取public权限的字段进行系列化和反系列化。如果没有public权限的字段,就会去获取public修饰的getter/setter。使用 JsonAutoDetect注解,我们就可以修改默认的行为。比如,下面的案例,即使字段都是private的、也没有getter/setter,也照样获取字段。
1、bean
首先,我们定义一个属性id/name都私有的而且没有getter/setter的一个bean
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import java.io.Serializable;
/**
* @author chushiyan
* @email chushiyan0415@163.com
* @description
*/
//@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean implements Serializable {
private String id;
private String name;
public PrivateBean() {
}
public PrivateBean(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "PrivateBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
2、反系列化测试:
@Test
public void testJsonAutoDetect() throws JsonProcessingException {
String json = "{"
+ "\"id\" : \"10\","
+ "\"name\" : \"chushiyan\""
+ "}";
ObjectMapper mapper = new ObjectMapper();
PrivateBean bean = mapper.readValue(json, PrivateBean.class);
System.out.println(bean);
}
报错:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "id" (class com.chushiyan.test.entity.PrivateBean), not marked as ignorable (0 known properties: ])
at [Source: (String)"{"id" : "10","name" : "chushiyan"}"; line: 1, column: 10] (through reference chain: com.chushiyan.test.entity.PrivateBean["id"])
3、系列化测试
@Test
public void testJsonAutoDetect2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
PrivateBean bean = new PrivateBean("11", "chushiyan");
String json = mapper.writeValueAsString(bean);
System.out.println(json);
}
报错:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.chushiyan.test.entity.PrivateBean and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
4、bean上加上注解
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import java.io.Serializable;
/**
* @author chushiyan
* @email chushiyan0415@163.com
* @description
*/
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PrivateBean implements Serializable {
private String id;
private String name;
public PrivateBean() {
}
public PrivateBean(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "PrivateBean{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
5、再次分别测试反系列化、系列化
都运行正常,分别打印:
PrivateBean{id='10', name='chushiyan'}
{"id":"11","name":"chushiyan"}