1. 程式人生 > >jackson學習之四:WRAP_ROOT_VALUE(root物件)

jackson學習之四:WRAP_ROOT_VALUE(root物件)

### 歡迎訪問我的GitHub [https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) 內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等; ### 系列文章彙總 - [jackson學習之一:基本資訊](https://blog.csdn.net/boling_cavalry/article/details/107135958) - [jackson學習之二:jackson-core](https://blog.csdn.net/boling_cavalry/article/details/108571629) - [jackson學習之三:常用API操作](https://blog.csdn.net/boling_cavalry/article/details/108192174) - [jackson學習之四:WRAP_ROOT_VALUE(root物件)](https://blog.csdn.net/boling_cavalry/article/details/108298858) - [jackson學習之五:JsonInclude註解](https://blog.csdn.net/boling_cavalry/article/details/108412558) - [jackson學習之六:常用類註解](https://blog.csdn.net/boling_cavalry/article/details/108333324) - [jackson學習之七:常用Field註解](https://blog.csdn.net/boling_cavalry/article/details/108589494) - [jackson學習之八:常用方法註解](https://blog.csdn.net/boling_cavalry/article/details/108433330) - [jackson學習之九:springboot整合(配置檔案)](https://blog.csdn.net/boling_cavalry/article/details/108460433) - [jackson學習之十(終篇):springboot整合(配置類)](https://blog.csdn.net/boling_cavalry/article/details/108559056) ### 本篇概覽 本文是《jackson學習》系列的第四篇,前面學習了常用API,可以執行最基本的序列化和反序列化操作,接下來要學習的就是jackson強大的註解能力,本篇要學的是root物件特性,主要內容如下: 1. 關於root物件 2. 測試用的POJO類 3. 序列化實戰 4. 反序列化實戰 ### 關於root物件(WRAP_ROOT_VALUE) 1. 對於只有id和name兩個欄位的POJO例項來說,正常的序列化結果如下: ```java { "id" : 1, "name" : "book" } ``` 2. jackson在序列化時,可以在上述json外面再包裹一層,官方叫做WRAP_ROOT_VALUE,本文中叫做root物件,如下所示,整個json的只有一個鍵值對,key是aaabbbccc,value內部才是POJO例項的id和name欄位的值: ```java { "aaabbbccc" : { "id" : 2, "name" : "food" } } ``` ### 提前小結 root物件特性提前做個小結,這樣如果您時間有限,僅看這一節即可: - 先看序列化場景: 1. 執行下面程式碼,jackson在序列化時會增加root物件: ```java mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); ``` 2. root物件的key,預設是例項的類名,如果例項有JsonRootName註解,就是該註解的value值; 3. root物件的value如下所示,相當於不支援root物件時的序列化結果: ```java { "id" : 1, "name" : "book" } ``` - 再看反序列化場景: 1. 執行下面程式碼,jackson在反序列化時會先解析root物件: ```java mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); ``` 2. root物件的key,預設是例項的類名,如果例項有JsonRootName註解,就是該註解的value值; 3. root物件的value如下所示,相當於不支援root物件時用來反序列化的json字串: ```java { "id" : 1, "name" : "book" } ``` ### 準備兩個POJO類 用對比的方式可以更清楚瞭解JsonRootName的作用,接下來的學習咱們準備兩個POJO類,一個沒有JsonRootName註解,另一個有JsonRootName註解: 1. 名為Order1.java的,沒有JsonRootName註解: ```java public class Order1 { private int id; private String name; // 省去get、set、toString方法 ... } ``` 2. 名為Order2.java的,有JsonRootName註解,value值為aaabbbccc: ```java import com.fasterxml.jackson.annotation.JsonRootName; @JsonRootName(value = "aaabbbccc") public class Order2 { private int id; private String name; // 省去get、set、toString方法 ... } ``` - 可見Order1和Order2的程式碼是一致的,唯一的不同是Order2帶有註解JsonRootName; ### 序列化 1. 需要設定WRAP_ROOT_VALUE屬性,jackson才會支援root物件,JsonRootName註解才會發揮作用,設定程式碼如下: ```java mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); ``` 2. 寫一段程式碼,在不開啟WRAP_ROOT_VALUE屬性的時候執行序列化,再開啟WRAP_ROOT_VALUE屬性執行序列化,對比試試: ```java public static void main(String[] args) throws Exception { // 例項化Order1和Order2 Order1 order1 = new Order1(); order1. setId(1); order1.setName("book"); Order2 order2 = new Order2(); order2. setId(2); order2.setName("food"); // 沒有開啟WRAP_ROOT_VALUE的時候 logger.info("沒有開啟WRAP_ROOT_VALUE\n"); ObjectMapper mapper1 = new ObjectMapper(); // 美化輸出 mapper1.enable(SerializationFeature.INDENT_OUTPUT); logger.info("沒有JsonRootName註解類,序列化結果:\n\n{}\n\n", mapper1.writeValueAsString(order1)); logger.info("有JsonRootName註解的類,序列化結果:\n\n{}\n\n\n\n", mapper1.writeValueAsString(order2)); // 開啟了WRAP_ROOT_VALUE的時候 logger.info("開啟了WRAP_ROOT_VALUE\n"); ObjectMapper mapper2 = new ObjectMapper(); // 美化輸出 mapper2.enable(SerializationFeature.INDENT_OUTPUT); // 序列化的時候支援JsonRootName註解 mapper2.enable(SerializationFeature.WRAP_ROOT_VALUE); logger.info("沒有JsonRootName註解類,序列化結果:\n\n{}\n\n", mapper2.writeValueAsString(order1)); logger.info("有JsonRootName註解的類,序列化結果:\n\n{}", mapper2.writeValueAsString(order2)); } ``` 3. 執行結果如下,JsonRootName在序列化時的作用一目瞭然:指定了root物件的key: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210129082337150-1671165597.jpg) ### 反序列化(預設設定) 1. 在沒有做任何設定的時候,下面這個字串用來反序列化成Order2物件,會成功嗎? ```json { "id" : 2, "name" : "food" } ``` 2. 試了下是可以的: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210129082338357-795860758.png) 3. 那下面這個字串能反序列化成Order2物件嗎? ```java { "aaabbbccc" : { "id" : 2, "name" : "food" } } ``` 4. 程式碼和結果如下圖所示,反序列化時jackson並不認識aaabbbccc這個key,因為jackson此時並不支援root物件: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210129082340518-1068299396.jpg) - 小結:預設情況下,反序列化時json字串不能有root物件; ### 反序列化(開啟UNWRAP_ROOT_VALUE屬性) 1. 如果開啟了UNWRAP_ROOT_VALUE屬性,用於反序列化的json字串就必須要有root物件了,開啟UNWRAP_ROOT_VALUE屬性的程式碼如下: ```java mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); ``` 2. 程式碼和結果如下圖,可見帶有root物件的json字串,可以反序列化成功,root物件的key就是JsonRootName註解的value屬性: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210129082341274-1631839837.jpg) 3. 值得注意的是,上述json字串中,root物件的key為aaabbbccc,這和Order2的JsonRootName註解的value值是一致的,如果不一致就會反序列化失敗,如下圖: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210129082342206-68813967.jpg) - 至此,jackson的WRAP_ROOT_VALUE特性就學習完成了,在web開發時這是個很常用的功能,用於在最外面包裹一層,以便整體上新增額外的內容,希望能給您帶來參考; ### 你不孤單,欣宸原創一路相伴 1. [Java系列](https://xinchen.blog.csdn.net/article/details/105068742) 2. [Spring系列](https://xinchen.blog.csdn.net/article/details/105086498) 3. [Docker系列](https://xinchen.blog.csdn.net/article/details/105086732) 4. [kubernetes系列](https://xinchen.blog.csdn.net/article/details/105086794) 5. [資料庫+中介軟體系列](https://xinchen.blog.csdn.net/article/details/105086850) 6. [DevOps系列](https://xinchen.blog.csdn.net/article/details/105086920) ### 歡迎關注公眾號:程式設計師欣宸 > 微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界... [https://github.com/zq2599/blog_demos](https://github.com/zq2599/blo