1. 初識Jackson -- 世界上最好的JSON庫

YourBatman發表於2020-07-23

生命太短暫,不要去做一些根本沒有人想要的東西。本文已被 https://www.yourbatman.cn 收錄,裡面一併有Spring技術棧、MyBatis、JVM、中介軟體等小而美的專欄供以免費學習。關注公眾號【BAT的烏托邦】逐個擊破,深入掌握,拒絕淺嘗輒止。

前言

各位小夥伴大家好,我是A哥。上篇文章 【Fastjson到了說再見的時候了】 A哥跟Fastjson說了拜拜,從本系列開始,我們將一起進入Jackson庫的學習。當然嘍說它是世界上最好的JSON庫並非一家之言,是官網上它自己說的,我免責申明哈。

一個工程僅需一個JSON庫

Java的JSON庫,你至少應該用過/聽過這三種:Jackson、Gson、Fastjson。一個獨立的工程,按照依賴最少原則,本應該only one JSON庫是足矣的。但現狀是:各位同仁可觀察觀察各自的專案,大都同時存在2種JSON庫,亦或者3種甚至更多...

說明:在同一個工程內,同一功能若有多種實現,實屬不好的現象。這會讓管理起來顯得混亂(譬如對日期的格式化就不方便做到統一),出口若有多個,想收口時就是個大難題了

作為一個合格的架構師/工程師,保持最簡依賴(一致性依賴)是應該有的技術範,因為簡單一致性它能帶來很大的收益,道理很簡單:兩個Java程式設計師的溝通/協同效率,一定會比1個Java + 1個Python溝通效率高。

so what,我們應該選擇哪一種JSON庫呢?答案顯而易見,那便是Jackson。因為它各個方面表現均非常優秀,是世界最流行、最好的JSON庫。把Jackson作為工程唯一JSON庫是有一丟丟門檻的(想想你為何使用Fastjson就知道啦),所以它來啦,祝你跨越此門檻,規範化使用,助你增加一項主流的硬核實力,這也是本專欄的最大意義所在


Jackson是世界最好的JSON庫

Jackson是一個簡單的、功能強大的、基於Java的應用庫。它可以很方便完成Java物件Json物件(xml文件or其它格式)進行互轉。Jackson社群相對比較活躍,更新速度也比較快。Jackson庫有如下幾大特性:

  • 高效能且穩定:低記憶體佔用,對大/小JSON串,大/小物件的解析表現均很優秀
  • 流行度高:是很多流行框架的預設選擇
  • 容易使用:提供高層次的API,極大簡化了日常使用案例
  • 無需自己手動建立對映:內建了絕大部分序列化時和Java型別的對映關係
  • 乾淨的JSON:建立的JSON具有乾淨、緊湊、體積小等特點
  • 無三方依賴:僅依賴於JDK
  • Spring生態加持:jackson是Spring家族的預設JSON/XML解析器(明白了吧,學完此專欄你對Spring都能更親近些了,一舉兩得)

版本約定:本專欄統一使用的版本號固定為2.11.0(2020-04釋出),GAV如下:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.11.1</version>
</dependency>

為了保持版本的統一性,後續的Spring Boot(2.3.0.RELEASE)/Spring Framework(5.2.6.RELEASE)使用的均為當前最新版本,因為它內建的jackson也恰好就是本專欄講解的版本。


正文

細心的朋友從上面的groupId裡可以看到:jackson它隸屬於fasterxml這個組織。本著追本溯源的精神,可以稍微的瞭解瞭解這個組織:fasterxml官網 截圖如下


簡單翻譯:FasterXML是Woodstox流的XML解析器、Jackson流的JSON解析器、Aalto非阻塞XML解析器以及不斷增長的實用程式庫和擴充套件家族背後的業務。

作為一個高度流行的開源庫,這種官網頁面應該重新整理了你的認知吧。並不是它內容不多,而其實是它的詳細介紹都發布在github上了,這便是接下來我們來認識它的主要渠道。

這種做法貌似已經成為了一種流行的趨勢:越來越多的開源軟體傾向於把github作為他們的Home Page了

fasterxml組織它直屬的一級工程其實也有不少:

  1. com.fasterxml.jackson
  2. com.fasterxml.uuid
  3. com.fasterxml.woodstox
  4. ...

很顯然,本專欄僅僅只會關注jackson工程,該工程便是該組織最出名且最最最為重要的部分。


官網介紹

瞭解一門新的技術,第一步應該就是看它的官網。上面已然解釋了,fasterxml組織它把各工程的首頁內容都託管在了github上,Jackson當然也不例外。Jackson官網 上對它自己有如下描述:

Jackson舊稱為:Java(或JVM平臺)的標準JSON庫,或者是Java的最佳JSON解析器,或者簡稱為“Java的JSON

從這名字就霸氣外露了,NB得不行,足以見得它在JSON解析方面的地位和流行程度,當然主要是自信

更重要的是,Jackson是一套JVM平臺的 資料處理(不限於JSON) 工具集:包括 一流的 JSON解析器/ JSON生成器、資料繫結庫(POJOs to and from JSON);並且提供了相關模組來支援 Avro, BSON, CBOR, CSV, Smile, Properties, Protobuf, XML or YAML等資料格式,甚至還支援大資料格式模組的設定。


分支:1.x和2.x

Jackson有兩個主要的分支:

  • 1.x分支,1.9.13。處於維護模式,只發布bug修復版本(最近一次釋出於Jul, 2013)
  • 2.x是正在開發的版本(持續更新升級中,2.0.0釋出於Mar, 2012)

注意:這兩個主要版本使用不同的Java包名和Maven GAV,因此它們並不相互相容,但可以和平共存。一個專案可以同時依賴於這兩個版本是沒有衝突的。這是經過設計而為之,選擇這種策略是為了更順利地從1.x進行遷移2. x

說明:現在都2020年了,1.x可以毫不客氣的說已經淘汰了(除了非常老的專案還在用),因此針對1.x版本本專欄不會有任何涉獵。

活躍的2.x分支說明

目前2.x分支存在如下活躍的分支們:

  • 2.12:下一個小版本,目前正在開發中
  • 2.11:當前穩定版。積極維護的分支,會積極持續釋出補丁
  • 2.10:上一個穩定的分支,沒有停止維護仍會發布補丁
  • 2.9: 非活躍分支,只會釋出微補丁了,雖然還活躍但活躍度較低
  • 其它2.x分支:只會釋出重大安全補丁
  • master:主分支。下一個主要分支3.0正在快速開發中

說明:對於2.11.0和2.11.x這種小分支之間的區別,可以忽略


模組介紹

Jackson是個開源的、且開放的社群。下面列出的大多數專案/模組是由Jackson開發團隊領導的,但也有一些來自Jackson社群的成員


三大核心模組

core module(核心模組) 是擴充套件模組構建的基礎。Jackson目前有3個核心模組:

說明:核心模組的groupId均為:<groupId>com.fasterxml.jackson.core</groupId>,artifactId見下面各模組所示

  • Streaming流處理模組(jackson-core):定義底層處理流的API:JsonPaser和JsonGenerator等,幷包含特定於json的實現。
  • Annotations標準註解模組(jackson-annotations):包含標準的Jackson註解
  • Databind資料繫結模組(jackson-databind):在streaming包上實現資料繫結(和物件序列化)支援;它依賴於上面的兩個模組,也是Jackson的高層API(如ObjectMapper)所在的模組

實際應用級開發中,我們只會使用到Databind資料繫結模組,so它是本系列重中之重。下面介紹那些舉足輕重的第三方模組


資料型別模組

這些擴充套件是Jackson外掛模組(通過ObjectMapper.registerModule()註冊,下同),並通過新增序列化器和反序列化器來對各種常用Java庫資料型別的支援,以便Jackson databind包(ObjectMapper / ObjectReader / ObjectWriter)能夠順利讀寫/轉換這些型別。

第三方模組有些是Jackson官方人員直接lead和維護的(主流模組),也有些是純社群行為。現在按照這兩個分類分別介紹一下各個模組的作用:

官方直接維護:

說明:官方維護的這些資料型別模組的groupId統一為:<groupId>com.fasterxml.jackson.datatype</groupId>,且版本號是和主版本號保持一致的

  • 標準集合資料型別模組:
    • Guava:支援Guava的集合資料型別
    • HPPC:略
    • PCollections:略 (Jackson 2.7新增的支援)
  • Hibernate:支援Hibernate的一些特性,如懶載入、proxy代理等
  • Joda:支援Joda date/time的資料型別
  • JDK7:對JDK7的支援(說明:2.7以後就無用了,以為2.7版本後最低的JDK版本要求是7)
  • Java8:它分為如下三個子模組來支援Java8
    • jackson-module-parameter-names:此模組能夠訪問建構函式和方法引數的名稱,從而允許省略@JsonProperty(當然前提是你必須加了編譯引數:-parameters
    • jackson-datatype-jsr310:支援Java8新增的JSR310時間API
    • jackson-datatype-jdk8:除了Java8的時間API外其它的API的支援,如Optional
  • JSR-353/org.json:略

非官方直接維護:

說明:非官方直接維護的這些模組groupId是不定的,每個模組可能都不一樣,並且它們的版本號不會隨著官方的主版本號一起走

  • jackson-datatype-bolts:對 Yandex Bolts collection types 的支援
  • jackson-datatype-commons-lang3:支援Apache Commons Lang v3裡面的一些型別
  • jackson-datatype-money:支援javax.money
  • jackson-datatype-json-lib:對久遠的json-lib這個庫的支援
  • ...

資料格式模組

Data format modules(資料格式模組)提供對JSON之外的資料格式的支援。它們中的大多數只是實現streaming API抽象,以便資料繫結元件可以按原樣使用。

官方直接維護:

說明:這些資料格式的模組的groupId均為<groupId>com.fasterxml.jackson.dataformat</groupId>,且跟著主版本號走

  • Avro/CBOR/Ion/Protobuf/Smile(binary JSON) :這些均屬於二進位制的資料格式,它們的artifactId為:<artifactId>jackson-dataformat-[FORMAT]</artifactId>
  • CSV/Properties/XML/YAML:這些格式熟悉吧,同樣的支援到了這些常用的文字格式

非官方直接維護:
因非官方直接維護的模組過於偏門,因此省略


JVM平臺其它語言

官網有說,Jackson是一個JVM平臺的解析器,因此語言層面不侷限於Java本身,還涵蓋了另外兩大主流JVM語言:Kotlin和Scala

說明:這塊的groupId均為:<groupId>com.fasterxml.jackson.module</groupId>,版本號跟著主版本號走

  • jackson-module-kotlin:處理kotlin源生型別
  • jackson-module-scala_[scala版本號]:處理scala源生型別

模式支援

Jackson註解為POJO定義了預期的屬性和預期的處理,除了Jackson本身將其用於讀取/寫入JSON和其他格式之外,它還允許生成外部模式。上面已講述的資料格式擴充套件中包含了部分功能,但也仍還有許多獨立的模式工具,如:

  • Ant Task for JSON Schema Generation:使用Apache Ant時,使用Jackson庫和擴充套件模組從Java類生成JSON
  • jackson-json-schema-maven-plugin:maven外掛,用於生成JSON
  • ...

說明:本部分因實際應用場景實在太少,為了不要混淆主要內容,此部分後面亦不會再提及


Jackson jr(用於移動端)

雖然Jackson databind(如ObjectMapper)是通用資料繫結的良好選擇,但它的佔用空間(Jar包大小)啟動開銷在某些領域可能存在問題:比如移動端,特別是對於輕量使用(讀或寫)。這種case下,完整的Jackson API是讓人接受不了的。

由於所有這些原因,Jackson官方決定建立一個更簡單、更小的庫:Jackson jr。它仍舊構建在Streaming API之上,但不依賴於databind和annotation。因此,它的大小(jar和執行時記憶體使用)要小得多,它的API非常緊湊,所以適合APP等移動端。

<dependency>
    <groupId>com.fasterxml.jackson.jr</groupId>
    <artifactId>jackson-jr-objects</artifactId>
</dependency>

它僅僅只依賴了jackson-core模組,所以體積上控制得非常的好。Jackson單單三大核心模組大小合計1700KB左右(320 + 70 + 1370)。而Jackson jr的體積控制在了95KB(就算加上core模組的320也不到500KB)。

而對於開發Java後臺的我們對記憶體並不敏感,簡單易用、功能強大才是硬道理。因此jackson-jr只是在此處做個簡單瞭解即可,本專欄後面也不會再提及。


漏洞報告

Jackson雖然已經足夠穩定並且安全了,但哪有聖人呢。針對它的相關漏洞報告,最近一次發生在2019-07-23FasterXML jackson-databind 遠端程式碼執行(CVE-2019-12384)
更多、更新的詳細漏洞報告參考連結(持續更新中):知道創宇Jackson漏洞報告


Java JSON庫比較

市面上的JSON庫非常之多,綜合一些Java人員的意見,關於使用哪個庫,這裡有一些現有的獨立比較的連結供以你參考:

說明:此處貼出的幾個參考連結均為官網給出的參考文章,均為國外較權威的文獻。

當然天朝的你可能更關心Jackson和Fastjson的對比,那暫先不用著急(雖然上文也比較過),這是本專欄後面的一道主菜,那裡會詳細道來。


總結

本文結合官網認識了Jackson的全貌,用全面的視角整體上把握到了Jackson所提供的功能模組,這為專欄後續的講解提供一個索引。

從Jackson的升級之快、模組支援之多足矣看得見它社群的活躍。並且為了迎合市場它在2.10版本後還提供了商業支援的服務:與Tidelift公司合作,為使用者構建應用程式的開源依賴項提供商業支援和維護。節省時間、降低風險和改善程式碼健康狀況(商業支援是收費的)。

相信通過本文你對Jackson有了個大概的瞭解,不出意外你應該是有興趣去學它了的。當你深入研究後會發現它的設計之優雅,擴充套件性之強,不是一般國產類庫所能比擬的。如果說Fastjson是一個優秀的JSON庫,那麼Jackson就是一個更優秀的JSON生態。


本專欄在CSDN付費,在公眾號全部免費公開,歡迎你關注A哥的公眾號【BAT的烏托邦】

相關文章