Jackson根据它的默认方式序列化和反序列化java对象,比如:默认情况下Jackson序列化或反序列化java对象是按对象属性进行一一匹配、返序列化json串里不能带特殊字符等。若根据实际需要,可以灵活的调整Jackson序列化和反序列化的规则。比如:可以设置ObjectMapper属性,也可以使用Jackson的注解。常用的注解及详细的使用方法如下:
(1)@JsonProperty注解
用于对象的属性,把属性的名称在序列化或反序列化时,转换为另外一个名称(默认是属性名称)。
#示例:UserInfo序列号后birthDate在json串的名称转为birth_date
@Data
public class UserInfo implements Serializable {
@JsonProperty("birth_date")
private Date birthDate;
private Integer age;
private String name;
private Long id;
}
#下面json串会反序列化失败,不识别birthDate字段
{"birthDate":"2020-11-20 10:43:57","id":100,"age":100,"name":"小米"}
#下面json串反序列化成功
{"birth_date":"2020-11-20 10:43:57","id":100,"age":100,"name":"小米"}
(2)@JsonFormat注解
用于属性或者Getter/Setter方法上,作用是把Date类型序列化成指定格式 和 把指定格式的时间字符串反序列化成Date类型。
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthDate;
#或者放在Getter/Setter方法上(Getter或Setter上效果一样,都能控制序列化和反序列化)
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
public Date getBirthDate(){
return birthDate;
}
注意:@JsonFormat注解和@DateTimeFormat的区别:前端请求Content-Type=application/json的post请求时,@JsonFormat规定接收的时间格式;前端表单提交时,@DateTimeFormat规定接收的时间格式。
(3)@JsonPropertyOrder注解
用于类的注解,指定属性在序列化时json中的顺序。(@JsonPropertyOrder注解的alphabetic属性可用于Json串里属性按字母顺序排列)
@JsonPropertyOrder({"birthDate", "id","age", "name"})
public class UserInfo{
private Long id;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date birthDate;
}
#最终序列化后,json中的顺序为@JsonPropertyOrder中指定的顺序。
{"birthDate":"2020-11-20 13:14:56","id":1000,"age":10,"name":"小强"}
#序列化后的json串按属性按字母顺序排列
@JsonPropertyOrder(alphabetic = true)
public class UserInfo{
private Long id;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date birthDate;
}
(4)@JsonCreator注解
用于构造方法,和 @JsonProperty配合使用,适用有参数的构造方法。作用就是指定反序列化时用哪个构造函数。
@Data
public class UserInfo implements Serializable {
private Long id;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date birthDate;
@JsonCreator //json反序列化时调用此构造函数
public UserInfo(@JsonProperty("name") String name) {
System.out.println("11111111111111111111111111111");
this.name = name;
}
public UserInfo() {
System.out.println("222222222222222222222222222");
}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = "{"birthDate":"2020-11-20 10:43:57","id":100,"age":100,"name":"小米"}";
UserInfo userInfo = mapper.readValue(jsonStr, UserInfo.class);
System.out.println(userInfo);
}
//输出:反序列化时使用的构造器是带@JsonCreator的构造器
11111111111111111111111111111
UserInfo(id=100, name=小米, age=100, birthDate=Fri Nov 20 18:43:57 CST 2020)
(5)@JsonIgnore注解
在Java对象序列化为json时 ,有些属性需要过滤掉不显示在 json中;反序列化时,即使json串中有属性的值,也不会注入对象。
@Data
public class UserInfo implements Serializable {
private Long id;
@JsonIgnore
private String name; //name序列化 和 反序列化时会被忽略掉
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date birthDate;
}
//测试类
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
UserInfo info = new UserInfo();
info.setAge(100);
info.setName("直播"); //name序列化会被忽略掉
info.setId(1000L);
info.setBirthDate(new Date());
String json = mapper.writeValueAsString(info);
System.out.println(json);
System.out.println("============================");
//name反序列化会被忽略掉
String json = "{"birthDate":"2020-11-20 10:43:57","id":100,"age":100,"name":"小米"}";
UserInfo userInfo = mapper.readValue(json, UserInfo.class);
System.out.println(userInfo);
}
//输出:name序列化 和 反序列化时都会被忽略掉
{"id":1000,"age":100,"birthDate":"2020-11-20 11:25:46"}
============================
UserInfo(id=100, name=null, age=100, birthDate=Fri Nov 20 18:43:57 CST 2020)
@JsonIgnoreProperties注解:对象序列化和反序列化时,忽略对象的多个属性。
@Data
public class PersonInfo implements Serializable {
private Long Id;
@JsonIgnoreProperties({"name", "age"})
private UserInfo userInfo;
}
#@JsonIgnoreProperties过滤多个属性:userInfo里的name和age在序列化和反序列化时会被忽略掉
(6)@JsonAnySetter注解
用于属性或者方法,设置未反序列化的属性名和值作为键值存储到map; @JsonAnyGetter用于方法 ,获取所有未序列化的属性。 所有被Ignore的属性 和 对象不存在的属性在反序列号时,都会调一次@JsonAnySetter的方法。
@Data
public class UserInfo implements Serializable {
private Long id;
@JsonIgnore
private String name;
private Integer age;
private Map<String, Object> map = new HashMap<>();
@JsonAnySetter
public void setOther(String key, Object value) {
System.out.println("key=" + key + " value=" + value);
map.put(key, value);
}
@JsonAnyGetter
public Map<String, Object> getOther() {
return map;
}
}
//测试方法
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
//反序列化时,因为Java对象name属性有@JsonIgnore会被忽略,Java对象没有birthDate会被忽略
String json = "{"birthDate":"2020-11-20 10:43:57","id":100,"age":100,"name":"小米"}";
UserInfo userInfo = mapper.readValue(jsonStr, UserInfo.class);
System.out.println(userInfo);
System.out.println(userInfo.any());
}
//输出:所有被Ignore的属性 和 对象不存在的属性在反序列号时,都会调一次@JsonAnySetter的方法。
key=birthDate value=2020-11-20 10:43:57
key=name value=小米
UserInfo(id=100, name=null, age=100, map={name=小米, birthDate=2020-11-20 10:43:57})
{name=小米, birthDate=2020-11-20 10:43:57}
(7)@JsonInclude注解
@JsonInclude(JsonInclude.Include.NON_NULL)注解,将该注解放在属性上,如果该属性为null则不参与序列化;如果放在类上边那对这个类的全部属性起作用。
#示例
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserInfo implements Serializable {
private Long id;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date birthDate;
}
#测试方法
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
UserInfo info = new UserInfo();
info.setName("消息");
info.setBirthDate(new Date());
System.out.println(mapper.writeValueAsString(info));
}
#输出:
{"name":"消息","birthDate":"2020-11-23 02:10:43"}
#UserInfo类去掉@JsonInclude注解后的输出:json字符串里会有null属性存在
{"id":null,"name":"消息","age":null,"birthDate":"2020-11-23 02:17:54"}
@JsonInclude注解除了NON_NULL的使用,还有其很多类型,详细参考JsonInclude.Include的枚举类。
#(1)@JsonInclude注解的属性常用的有一下几种:
Include.Include.ALWAYS 默认
Include.NON_DEFAULT 属性为默认值不序列化
Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化
Include.NON_NULL 属性为NULL 不序列化
#(2)对象属性为null不参与序列化,除了使用注解外,也可以直接设置ObjectMapper属性,如下:
ObjectMapper mapper = new ObjectMapper();
//类型的设置也包含上面四种
mapper.setSerializationInclusion(Include.NON_NULL);
最后,感觉在平时的开发中好多人喜欢用阿里的fastjson,官方评价说是最快的json解析框架,但最近几年经常出高危漏洞,项目也跟着不断打复补丁,有时候搞得人心惶惶的,特别被动。于是为了不重复造轮子都将Jackson封装成统一的工具。