歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類匯總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;
系列文章匯總
- jackson學習之一:基本資訊
- jackson學習之二:jackson-core
- jackson學習之三:常用API操作
- jackson學習之四:WRAP_ROOT_VALUE(root物件)
- jackson學習之五:JsonInclude注解
- jackson學習之六:常用類注解
- jackson學習之七:常用Field注解
- jackson學習之八:常用方法注解
- jackson學習之九:springboot整合(組態檔)
- jackson學習之十(終篇):springboot整合(配置類)
本篇概覽
- 本文是《jackson學習》系列的第八篇,繼續學習jackson強大的注解能力,本篇學習常用的方法注解,并通過實體來加深印象,下圖是常用方法注解的簡介:

原始碼下載
- 如果您不想編碼,可以在GitHub下載所有原始碼,地址和鏈接資訊如下表所示(https://github.com/zq2599/blog_demos):
| 名稱 | 鏈接 | 備注 |
|---|---|---|
| 專案主頁 | https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 |
| git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協議 |
| git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |
- 這個git專案中有多個檔案夾,本章的應用在jacksondemo檔案夾下,如下圖紅框所示:

- jacksondemo是父子結構的工程,本篇的代碼在annotation子工程中,里面的methodannotation這個package下,如下圖:

JsonValue
- 在序列化時起作用,可以用來注解get方法或者成員變數;
- 一個類中,JsonValue只允許出現一次;
- 如果注解的是get方法,那么該方法的回傳值就是整個實體的序列化結果;
- 如果注解的是成員變數,那么該成員變數的值就是整個實體的序列化結果;
- 下面是用來測驗的Pojo類,JsonValue注解放在getField0方法上,此方法的回傳值已經寫死了"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類的序列化結果如下,即getField0方法的回傳值:

JsonCreator
- 在反序列化時,當出現有參構造方法時(可能是多個有參構造方法),需要通過JsonCreator注解指定反序列化時用哪個構造方法,并且在入參處還要通過JsonProperty指定欄位關系:
static class Test {
private String field0;
private String field1;
public Test(String field0) {
this.field0 = field0;
}
// 通過JsonCreator指定反序列化的時候使用這個構造方法
// 通過JsonProperty指定欄位關系
@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 + '\'' +
'}';
}
}
- 反序列化結果如下:

JsonSetter
- JsonSetter注解在set方法上,被用來在反序列化時指定set方法對應json的哪個屬性;
- JsonSetter原始碼中,推薦使用JsonProperty來取代JsonSetter:

3. 測驗代碼和結果如下,可見反序列化時,是按照JsonSetter的value去json中查找屬性的:

JsonGetter
- JsonGetter只能作為方法注解;
- 在序列化時,被JsonGetter注解的get方法,對應的json欄位名是JsonGetter的value;
- JsonGetter原始碼中,推薦使用JsonProperty來取代JsonGetter:

4. 測驗代碼和結果如下,可見序列化時JsonGetter的value會被作為json欄位名:

JsonAnyGetter
- JsonAnyGetter的作用有些特別:在序列化時,用Map物件的鍵值對轉成json的欄位和值;
- 理解JsonAnyGetter最好的辦法,是對比使用前后序列化結果的變化,先來看以下這段代碼,是沒有JsonAnyGetter注解的,Test有兩個成員變數,其中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);
// 新增一個HashMap,里面放入兩個元素
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));
}
}
- 上述代碼的執行結果如下,其實很好理解,就是field0和map兩個欄位而已:
{
"field0" : "000",
"map" : {
"aaa" : "value_aaa",
"bbb" : "value_bbb"
}
}
- 接下來,對上述代碼做一處改動,如下圖紅框所示,給getMap方法增加JsonAnyGetter注解:

5. 修改后的執行結果如下,原來的map欄位沒有了,map內部的所有鍵值對都成了json的欄位:
{
"field0" : "000",
"aaa" : "value_aaa",
"bbb" : "value_bbb"
}
- 至此,可以品味出JsonAnyGetter的作用了:序列化時,將Map中的鍵值對全部作為JSON的欄位輸出;
JsonAnySetter
- 弄懂了前面的JsonAnyGetter,對于JsonAnySetter的作用想必您也能大致猜到:反序列化時,對json中不認識的欄位,統統呼叫JsonAnySetter注解修飾的方法去處理;
- 測驗的代碼如下,Test類的setValue方法被JsonAnySetter注解,在反序列化時,json中的aaa和bbb欄位,都會交給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));
}
}
- 執行結果如下,可見aaa、bbb都被放入了map中:
Test{field0='null', map={aaa=value_aaa, field0=000, bbb=value_bbb}}
- 另外JsonAnySetter還可以作用在成員變數上,上面的代碼中,去掉setValue方法,在成員變數map上增加JsonAnySetter注解,修改后如下,執行結果也是一模一樣的:
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作用在成員變數上時,該成員變數必須是java.util.Map的實作類;
- 至此,Jackson常用注解已全部實戰完畢,希望這些豐富的注解能助您制定出各種靈活的序列化和反序列化策略;
你不孤單,欣宸原創一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 資料庫+中間件系列
- DevOps系列
歡迎關注公眾號:程式員欣宸
微信搜索「程式員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/256684.html
標籤:其他
