@JsonIgnore,@JsonValue,@JsonCreator
通过具体的代码测试,来说明三者的作用。
两个名词:
序列化:实体转为Json格式,比如Controller层,返回给前端。
反序列化:Json格式数据转为实体,比如前端传递Json数据给Controller。
@JsonIgnore
注解在哪个字段上,则这个字段不会参与序列化和反序列化。
// @JsonIgnore
@Test
public void test01() throws Exception {
Student student = new Student();
student.setId(1L);
student.setEmail("xiaolaoben@233.com");
student.setTelphone("12312311122");
student.setUserName("小老犇");
// 不加注解,效果
String json = JacksonUtils.obj2json(student);
System.out.println("不加注解,效果:all you(都有)" + json); // {"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com"}
// // 加注解,序列化时,@JsonIgnore效果
String pojotojson = JacksonUtils.obj2json(student);
System.out.println("序列化时,效果:忽略电话字段值" + pojotojson); // {"id":1,"userName":"小老犇","email":"xiaolaoben@233.com"}
// // 加注解,反序列化时,@JsonIgnore效果
String jsonToPojo = "{\"id\":1,\"userName\":\"小老犇\",\"telphone\":\"12312311122\",\"email\":\"xiaolaoben@233.com\"}";
Student pojo = JacksonUtils.json2pojo(jsonToPojo, Student.class);
System.out.println("反序列化时,效果:忽略电话字段值" + pojo); // Student(id=1, userName=小老犇, telphone=null, email=xiaolaoben@233.com)
}
@JsonValue
序列化时,指定将枚举字段,反序列化为什么值。
常用于枚举类中,注解在getCode()方法上,返回给前端code,数字。
@Test
public void test02() throws Exception {
// 不使用注解
// String no = JacksonUtils.obj2json(StudentEnum.FEMALE);
// System.out.println("不使用注解,效果:同英文名" + no); // "FEMALE"
// 使用注解
String have = JacksonUtils.obj2json(StudentEnum.FEMALE);
System.out.println("使用注解,效果:对应字段的值" + have);// 1002
}
// 开发过程中,Controller层序列化实体类,即后端to前端的过程。
@Test
public void test03() throws Exception {
Student student = new Student();
student.setId(1L);
student.setEmail("xiaolaoben@233.com");
student.setTelphone("12312311122");
student.setUserName("小老犇");
student.setSex(StudentEnum.FEMALE);
// 不使用注解
String no = JacksonUtils.obj2json(student);
System.out.println("不使用注解,效果:同英文名" + no); // {"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com","sex":"FEMALE"}
// 使用注解
String have = JacksonUtils.obj2json(student);
System.out.println("使用注解,效果:对应字段的值" + have);// {"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com","sex":1002}
}
@JsonCreator
用于反序列化时,指定构造方法,可以在构造方法内部,进行业务处理,常用于枚举类中。
比如:
我们自定义的枚举类,往往是有自己的code,比如FEMALE(1002, “女性”)中的1002,相对应的前端传过来的,和数据库中存的也都是1002。
如果我们不使用JsonCreator,那么我们的1002,就会没有作用,前端传过来的数据,直接报错,反序列化失败。
不使用注解
@Test
public void test04() throws Exception {
String no = "{\"id\":1,\"userName\":\"小老犇\",\"telphone\":\"12312311122\",\"email\":\"xiaolaoben@233.com\",\"sex\":0}";
Student pojo = JacksonUtils.json2pojo(no, Student.class);
System.out.println(pojo);
}
此时,枚举中自定义的code无效,使用枚举类内置下标ordinal,从0开始排序,可以反序列化成功。
若传入code不在枚举类中默认code,则报错:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.huwei.system.StudentEnum` from number -1: index value outside legal index range [0..2] at [Source: (String)"{"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com","sex":-1}"; line: 1, column: 86] (through reference chain: com.huwei.system.Student["sex"])
使用注解
@Test
public void test05() throws Exception {
String have = "{\"id\":1,\"userName\":\"小老犇\",\"telphone\":\"12312311122\",\"email\":\"xiaolaoben@233.com\",\"sex\":1002}";
Student student = JacksonUtils.json2pojo(have, Student.class);
System.out.println(student);
}
Jackson在反序列化的时候,会使用实体的默认无参构造函数来实例化一个对象,然后使用对象的setter方法来初始化属性值。
现在我们在反序列化Student类,查看控制台日志(如图):
可以看出,现在@JsonCreator注解生效,反序列化Student类时,其中枚举字段的构造,走的是我们自定义的构造方法,通过处理,返回我们的枚举字段。此时,自定义的code生效。
测试代码:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.stream.Stream;
public enum StudentEnum {
UNKNOWN(0, "未知"),
MALE(1001, "男性"),
FEMALE(1002, "女性"),
NOMALE(1003, "妖怪");
private String desc;
private int code;
StudentEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
public String getDesc() {
return this.desc;
}
@JsonValue
public Integer getCode() {
return this.code;
}
@JsonCreator
public static StudentEnum forValue(Integer value) {
System.out.println("我在走枚举类型的自定义构造方法!");
StudentEnum[] values = StudentEnum.values();
return Stream.of(values).filter(it -> it.getCode().equals(value)).findAny().orElse(UNKNOWN);
}
}
import io.swagger.annotations.ApiModelProperty;
/**
* @author jjsai
* @date 2021/7/11 19:05
**/
public class Student {
@ApiModelProperty(value = "主键")
private Long id;
@ApiModelProperty(value = "用户名")
private String userName;
@ApiModelProperty(value = "手机号")
private String telphone;
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "性别")
private StudentEnum sex;
public Student() {
System.out.println("我在走student的空参构造");
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getTelphone() {
return telphone;
}
public void setTelphone(String telphone) {
this.telphone = telphone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public StudentEnum getSex() {
return sex;
}
public void setSex(StudentEnum sex) {
System.out.println("我在走Student类中的枚举字段sex的set方法");
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", userName='" + userName + '\'' +
", telphone='" + telphone + '\'' +
", email='" + email + '\'' +
", sex=" + sex +
'}';
}
}
import org.junit.jupiter.api.Test;
/**
* @author jjsai
* @date 2021/7/11 19:01
**/
public class JacksonTest {
// @JsonIgnore
@Test
public void test01() throws Exception {
Student student = new Student();
student.setId(1L);
student.setEmail("xiaolaoben@233.com");
student.setTelphone("12312311122");
student.setUserName("小老犇");
// 不加注解,效果
String json = JacksonUtils.obj2json(student);
System.out.println("不加注解,效果:all you(都有)" + json); // {"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com"}
// // 加注解,序列化时,@JsonIgnore效果
String pojotojson = JacksonUtils.obj2json(student);
System.out.println("序列化时,效果:忽略电话字段值" + pojotojson); // {"id":1,"userName":"小老犇","email":"xiaolaoben@233.com"}
// // 加注解,反序列化时,@JsonIgnore效果
String jsonToPojo = "{\"id\":1,\"userName\":\"小老犇\",\"telphone\":\"12312311122\",\"email\":\"xiaolaoben@233.com\"}";
Student pojo = JacksonUtils.json2pojo(jsonToPojo, Student.class);
System.out.println("反序列化时,效果:忽略电话字段值" + pojo); // Student(id=1, userName=小老犇, telphone=null, email=xiaolaoben@233.com)
}
// JsonValue
@Test
public void test02() throws Exception {
// 不使用注解
String no = JacksonUtils.obj2json(StudentEnum.FEMALE);
System.out.println("不使用注解,效果:同英文名" + no); // "FEMALE"
// 加上注解效果
String have = JacksonUtils.obj2json(StudentEnum.FEMALE);
System.out.println("使用注解,效果:对应字段的值" + have);// 1002
}
// 序列化实体类,即后端to前端的过程。
@Test
public void test03() throws Exception {
Student student = new Student();
student.setId(1L);
student.setEmail("xiaolaoben@233.com");
student.setTelphone("12312311122");
student.setUserName("小老犇");
student.setSex(StudentEnum.FEMALE);
// 不使用注解
String no = JacksonUtils.obj2json(student);
System.out.println("不使用注解,效果:同英文名" + no); // {"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com","sex":"FEMALE"}
// 使用注解
String have = JacksonUtils.obj2json(student);
System.out.println("使用注解,效果:对应字段的值" + have);// {"id":1,"userName":"小老犇","telphone":"12312311122","email":"xiaolaoben@233.com","sex":1002}
}
// @JsonCreator 不使用注解
@Test
public void test04() throws Exception {
String no = "{\"id\":1,\"userName\":\"小老犇\",\"telphone\":\"12312311122\",\"email\":\"xiaolaoben@233.com\",\"sex\":0}";
Student pojo = JacksonUtils.json2pojo(no, Student.class);
System.out.println(pojo);
}
// @JsonCreator 使用注解
@Test
public void test05() throws Exception {
String have = "{\"id\":1,\"userName\":\"小老犇\",\"telphone\":\"12312311122\",\"email\":\"xiaolaoben@233.com\",\"sex\":1002}";
Student student = JacksonUtils.json2pojo(have, Student.class);
System.out.println(student);
}
}
JacksonUtils工具类网上随便找一个就好。
比如:
完事!