Jackson(3)之常用注解使用

Jackson根据它的默认方式序列化和反序列化java对象,比如:默认情况下Jackson序列化或反序列化java对象是按对象属性进行一一匹配、返序列化json串里不能带特殊字符等。若根据实际需要,可以灵活的调整Jackson序列化和反序列化的规则。比如:可以设置ObjectMapper属性(详细请参考: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规定接收的时间格式。(详细请参考:@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封装成统一的工具。参考json工具:JsonUtils工具类

       

                                                                                                                          2020年12月06日  晚  于北京记

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值