https://github.com/zq2599/blog_demos
內(nèi)容:所有原創(chuàng)文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;
本文是《jackson學(xué)習(xí)》系列的第八篇,繼續(xù)學(xué)習(xí)jackson強(qiáng)大的注解能力,本篇學(xué)習(xí)常用的方法注解,并通過實(shí)例來加深印象,下圖是常用方法注解的簡(jiǎn)介:
如果您不想編碼,可以在GitHub下載所有源碼,地址和鏈接信息如下表所示(https://github.com/zq2599/blog_demos):
名稱 | 鏈接 | 備注 |
---|---|---|
項(xiàng)目主頁(yè) | https://github.com/zq2599/blog_demos | 該項(xiàng)目在GitHub上的主頁(yè) |
git倉(cāng)庫(kù)地址(https) | https://github.com/zq2599/blog_demos.git | 該項(xiàng)目源碼的倉(cāng)庫(kù)地址,https協(xié)議 |
git倉(cāng)庫(kù)地址(ssh) | git@github.com:zq2599/blog_demos.git | 該項(xiàng)目源碼的倉(cāng)庫(kù)地址,ssh協(xié)議 |
這個(gè)git項(xiàng)目中有多個(gè)文件夾,本章的應(yīng)用在jacksondemo文件夾下,如下圖紅框所示:
jacksondemo是父子結(jié)構(gòu)的工程,本篇的代碼在annotation子工程中,里面的methodannotation這個(gè)package下,如下圖:
在序列化時(shí)起作用,可以用來注解get方法或者成員變量;
一個(gè)類中,JsonValue只允許出現(xiàn)一次;
如果注解的是get方法,那么該方法的返回值就是整個(gè)實(shí)例的序列化結(jié)果;
如果注解的是成員變量,那么該成員變量的值就是整個(gè)實(shí)例的序列化結(jié)果;
下面是用來測(cè)試的Pojo類,JsonValue注解放在getField0方法上,此方法的返回值已經(jīng)寫死了"abc":
static class Test { private String field0; private String field1; @JsonValue public String getField0() { return "abc"; } public void setField0(String field0) { this.field0 = field0; } public String getField1() { return field1; } public void setField1(String field1) { this.field1 = field1; } }
Test類的序列化結(jié)果如下,即getField0方法的返回值:
在反序列化時(shí),當(dāng)出現(xiàn)有參構(gòu)造方法時(shí)(可能是多個(gè)有參構(gòu)造方法),需要通過JsonCreator注解指定反序列化時(shí)用哪個(gè)構(gòu)造方法,并且在入?yún)⑻庍€要通過JsonProperty指定字段關(guān)系:
static class Test { private String field0; private String field1; public Test(String field0) { this.field0 = field0; } // 通過JsonCreator指定反序列化的時(shí)候使用這個(gè)構(gòu)造方法 // 通過JsonProperty指定字段關(guān)系 @JsonCreator public Test(@JsonProperty("field0") String field0, @JsonProperty("field1") String field1) { this.field0 = field0; this.field1 = field1; } @Override public String toString() { return "Test{" + "field0='" + field0 + '\'' + ", field1='" + field1 + '\'' + '}'; } }
反序列化結(jié)果如下:
JsonSetter注解在set方法上,被用來在反序列化時(shí)指定set方法對(duì)應(yīng)json的哪個(gè)屬性;
JsonSetter源碼中,推薦使用JsonProperty來取代JsonSetter:
JsonGetter只能作為方法注解;
在序列化時(shí),被JsonGetter注解的get方法,對(duì)應(yīng)的json字段名是JsonGetter的value;
JsonGetter源碼中,推薦使用JsonProperty來取代JsonGetter:
JsonAnyGetter的作用有些特別:在序列化時(shí),用Map對(duì)象的鍵值對(duì)轉(zhuǎn)成json的字段和值;
理解JsonAnyGetter最好的辦法,是對(duì)比使用前后序列化結(jié)果的變化,先來看以下這段代碼,是沒有JsonAnyGetter注解的,Test有兩個(gè)成員變量,其中map字段是HashMap類型的:
package com.bolingcavalry.jacksondemo.annotation.methodannotation;import com.fasterxml.jackson.annotation.JsonAnyGetter;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import java.util.HashMap;import java.util.Map;public class JsonAnySetterSerialization { static class Test { private String field0; private Map<String, Object> map; public String getField0() { return field0; } public void setField0(String field0) { this.field0 = field0; } public void setMap(Map<String, Object> map) { this.map = map; } public Map<String, Object> getMap() { return map; } } public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 美化輸出 mapper.enable(SerializationFeature.INDENT_OUTPUT); // 新增一個(gè)HashMap,里面放入兩個(gè)元素 Map<String, Object> map = new HashMap<>(); map.put("aaa", "value_aaa"); map.put("bbb", "value_bbb"); Test test = new Test(); test.setField0("000"); // map賦值給test.map test.setMap(map); System.out.println(mapper.writeValueAsString(test)); }}
上述代碼的執(zhí)行結(jié)果如下,其實(shí)很好理解,就是field0和map兩個(gè)字段而已:
{ "field0" : "000", "map" : { "aaa" : "value_aaa", "bbb" : "value_bbb" }}
接下來,對(duì)上述代碼做一處改動(dòng),如下圖紅框所示,給getMap方法增加JsonAnyGetter注解:
{ "field0" : "000", "aaa" : "value_aaa", "bbb" : "value_bbb"}
至此,可以品味出JsonAnyGetter的作用了:序列化時(shí),將Map中的鍵值對(duì)全部作為JSON的字段輸出;
弄懂了前面的JsonAnyGetter,對(duì)于JsonAnySetter的作用想必您也能大致猜到:反序列化時(shí),對(duì)json中不認(rèn)識(shí)的字段,統(tǒng)統(tǒng)調(diào)用JsonAnySetter注解修飾的方法去處理;
測(cè)試的代碼如下,Test類的setValue方法被JsonAnySetter注解,在反序列化時(shí),json中的aaa和bbb字段,都會(huì)交給setValue方法處理,也就是放入map中:
package com.bolingcavalry.jacksondemo.annotation.methodannotation;import com.fasterxml.jackson.annotation.JsonAnySetter;import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonProperty;import com.fasterxml.jackson.databind.ObjectMapper;import java.util.HashMap;import java.util.Map;public class JsonAnySetterDeserialization { static class Test { private String field0; private Map<String, Object> map = new HashMap<>(); @JsonAnySetter public void setValue(String key, Object value) { map.put(key, value); } @Override public String toString() { return "Test{" + "field0='" + field0 + '\'' + ", map=" + map + '}'; } } public static void main(String[] args) throws Exception { String jsonStr = "{\n" + " \"field0\" : \"000\",\n" + " \"aaa\" : \"value_aaa\",\n" + " \"bbb\" : \"value_bbb\"\n" + "}"; System.out.println(new ObjectMapper().readValue(jsonStr, Test.class)); }}
執(zhí)行結(jié)果如下,可見aaa、bbb都被放入了map中:
Test{field0='null', map={aaa=value_aaa, field0=000, bbb=value_bbb}}
另外JsonAnySetter還可以作用在成員變量上,上面的代碼中,去掉setValue方法,在成員變量map上增加JsonAnySetter注解,修改后如下,執(zhí)行結(jié)果也是一模一樣的:
static class Test { private String field0; @JsonAnySetter private Map<String, Object> map = new HashMap<>(); @Override public String toString() { return "Test{" + "field0='" + field0 + '\'' + ", map=" + map + '}'; } }
注意,JsonAnySetter作用在成員變量上時(shí),該成員變量必須是java.util.Map的實(shí)現(xiàn)類;
至此,Jackson常用注解已全部實(shí)戰(zhàn)完畢,希望這些豐富的注解能助您制定出各種靈活的序列化和反序列化策略;
聯(lián)系客服