【Jackson 框架】序列化和反序列化
Jackson 是當前用的比較廣泛的,用來序列化和反序列化 json 的 Java 的開源框架。Jackson 社 區相對比較活躍,更新速度也比較快, 從 Github 中的統計來看,Jackson 是最流行的 json 解析器之一 。 Spring MVC 的預設 json 解析器便是 Jackson。 Jackson 優點很多。 Jackson 所依賴的 jar 包較少 ,簡單易用。與其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 檔案速度比較快;Jackson 執行時佔用記憶體比較低,效能比較好;Jackson 有靈活的 API,可以很容易進行擴充套件和定
Jackson 的 1.x 版本的包名是 org.codehaus.jackson ,當升級到 2.x 版本時,包名變為 com.fasterxml.jackson,本文討論的內容是基於最新的 Jackson 的 2.9.1 版本。
Jackson 的核心模組由三部分組成。
- jackson-core,核心包,提供基於"流模式"解析的相關 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 內部實現正是通過高效能的流模式 API 的 JsonGenerator 和 JsonParser 來生成和解析 json。
- jackson-annotations,註解包,提供標準註解功能;
- jackson-databind ,資料繫結包, 提供基於"物件繫結" 解析的相關 API ( ObjectMapper ) 和"樹模型" 解析的相關 API (JsonNode);基於"物件繫結" 解析的 API 和"樹模型"解析的 API 依賴基於"流模式"解析的 API。
在瞭解 Jackson 的概要情況之後,下面介紹 Jackson 的基本用法。
Jackson 的 基本用法
若想在 Java 程式碼中使用 Jackson 的核心模組的 jar 包 ,需要在 pom.xml 中新增如下資訊。
清單 1.在 pom.xml 的 Jackson 的配置資訊
1 2 3 4 5 |
|
jackson-databind 依賴 jackson-core 和 jackson-annotations,當新增 jackson-databind 之後, jackson-core 和 jackson-annotations 也隨之新增到 Java 專案工程中。在新增相關依賴包之後,就可以使用 Jackson。
ObjectMapper 的 使用
Jackson 最常用的 API 就是基於"物件繫結" 的 ObjectMapper。下面是一個 ObjectMapper 的使用的簡單示例。
清單 2 . ObjectMapper 使用示例
1 2 3 4 5 6 7 |
|
ObjectMapper 通過 writeValue 系列方法 將 java 對 象序列化 為 json,並 將 json 存 儲成不同的格式,String(writeValueAsString),Byte Array(writeValueAsString),Writer, File,OutStream 和 DataOutput。
ObjectMapper 通過 readValue 系列方法從不同的資料來源像 String , Byte Array, Reader,File,URL, InputStream 將 json 反序列化為 java 物件。
資訊配置
在呼叫 writeValue 或呼叫 readValue 方法之前,往往需要設定 ObjectMapper 的相關配置資訊。這些配置資訊應用 java 物件的所有屬性上。示例如下:
清單 3 . 配置資訊使用示例
1 2 3 4 5 6 7 8 9 |
|
更多配置資訊可以檢視 Jackson 的 DeserializationFeature,SerializationFeature 和 I nclude。
Jackson 的 註解的使用
Jackson 根據它的預設方式序列化和反序列化 java 物件,若根據實際需要,靈活的調整它的預設方式,可以使用 Jackson 的註解。常用的註解及用法如下。
表 1. Jackson 的 常用註解
註解 | 用法 |
---|---|
@JsonProperty | 用於屬性,把屬性的名稱序列化時轉換為另外一個名稱。示例: @JsonProperty("birth_ d ate") private Date birthDate; |
@JsonFormat | 用於屬性或者方法,把屬性的格式序列化時轉換成指定的格式。示例: @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm") public Date getBirthDate() |
@JsonPropertyOrder | 用於類, 指定屬性在序列化時 json 中的順序 , 示例: @JsonPropertyOrder({ "birth_Date", "name" }) public class Person |
@JsonCreator | 用於構造方法,和 @JsonProperty 配合使用,適用有引數的構造方法。 示例: @JsonCreator public Person(@JsonProperty("name")String name) {…} |
@JsonAnySetter | 用於屬性或者方法,設定未反序列化的屬性名和值作為鍵值儲存到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); } |
@JsonAnyGetter | 用於方法 ,獲取所有未序列化的屬性 public Map<String, Object> any() { return map; } |
在瞭解 Jackson 的基本用法後,下面詳細地介紹它的一些高階應用。
Jackson 的 高階應用
格式處理(含日期格式)
不同型別的日期型別,Jackson 的處理方式也不同。
- 對於日期型別為 java.util.Calendar,java.util.GregorianCalendar,java.sql.Date,java.util.Date,java.sql.Timestamp,若不指定格式, 在 json 檔案中將序列化 為 long 型別的資料。顯然這種預設格式,可讀性差,轉換格式是必要的。Jackson 有 很多方式轉換日期格式。
- 註解方式,請參照" Jackson 的註解的使用"的@ JsonFormat 的示例。
- ObjectMapper 方式,呼叫 ObjectMapper 的方法 setDateFormat,將序列化為指定格式的 string 型別的資料。
- 對於日期型別為 java.time.LocalDate,還需要新增程式碼 mapper.registerModule(new JavaTimeModule()),同時新增相應的依賴 jar 包
清單 4 . JSR31 0 的配置資訊
1 2 3 4 5 |
|
對於 Jackson 2.5 以下版本,需要新增程式碼 objectMapper.registerModule(new JSR310Module ())
- 對於日期型別為 org.joda.time.DateTime,還需要新增程式碼 mapper.registerModule(new JodaModule()),同時新增相應的依賴 jar 包
清單 5. joda 的 配置資訊
1 2 3 4 5 |
|
泛型反序列化
Jackson 對泛型反序列化也提供很好的支援。
- 對於 List 型別 ,可以呼叫 constructCollectionType 方法來序列化,也可以構造 TypeReference 來序列化。
清單 6 . List 泛 型使用示例
1 2 3 4 5 |
|
- 對於 map 型別, 與 List 的實現方式相似。
清單 7 . Map 泛型使用示例
1 2 3 4 5 6 7 8 |
|
Array 和 Collection 的處理與 List,Map 相似,這裡不再詳述。
屬性視覺化
是 java 物件的所有的屬性都被序列化和反序列化,換言之,不是所有屬性都視覺化,預設的屬性視覺化的規則如下:
- 若該屬性修飾符是 public,該屬性可序列化和反序列化。
- 若屬性的修飾符不是 public,但是它的 getter 方法和 setter 方法是 public,該屬性可序列化和反序列化。因為 getter 方法用於序列化, 而 setter 方法用於反序列化。
- 若屬性只有 public 的 setter 方法,而無 public 的 getter 方 法,該屬性只能用於反序列化。
若想更改預設的屬性視覺化的規則,需要呼叫 ObjectMapper 的方法 setVisibility。
下面的示例使修飾符為 protected 的屬性 name 也可以序列化和反序列化。
清單 8 . 屬性視覺化示例
1 2 3 4 5 6 7 8 |
|
屬性過濾
在將 Java 物件序列化為 json 時 ,有些屬性需要過濾掉,不顯示在 json 中 , Jackson 有多種實現方法。
- 註解方式, 可以用 @JsonIgnore 過濾單個屬性或用 @JsonIgnoreProperties 過濾多個屬性,示例如下:
清單 9 . 屬性過濾示例一
1 2 3 4 |
|
- addMixIn 方法加註解方式@JsonIgnoreProperties。
addMixIn 方法簽名如下:
public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource);
addMixIn 方法的作用是用 mixinSource 介面或類的註解會重寫 target 或 target 的子型別的註解。 用ixIn 設定
Person peixIn 的 @JsonIgnoreProperties("name")所重寫,最終忽略的屬性為 name,最終生成的 json 如下:
{"birthDate":"2017/09/13","age":40}
- SimpleBeanPropertyFilter 方式。這種方式比前兩種方式更加靈活,也更復雜一些。
首先需要設定@JsonFilter 類或介面,其次設定 addMixIn,將@JsonFilter 作用於 java 物件上,最後呼叫 SimpleBeanPropertyFilter 的 serializeAllExcept 方法或重寫 S impleBeanPropertyFilter 的 serializeAsField 方法來過濾相關屬性。示例如下:
清單 11 . 屬性過濾示例三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
自定義序列化和反序列化
當 Jackson 預設序列化和反序列化的類不能滿足實際需要,可以自定義新的序列化和反序列化的類。
- 自定義序列化類。自定義的序列化類需要直接或間接繼承 StdSerializer 或 JsonSerializer,同時需要利用 JsonGenerator 生成 json,重寫方法 serialize,示例如下:
清單 12 . 自定義序列化
1 2 3 4 5 6 7 8 9 10 |
|
JsonGenerator 有多種 write 方法以支援生成複雜的型別的 json,比如 writeArray,writeTree 等 。若想單獨建立 JsonGenerator,可以通過 JsonFactory() 的 createGenerator。
- 自定義反序列化類。自定義的反序列化類需要直接或間接繼承 StdDeserializer 或 StdDeserializer,同時需要利用 JsonParser 讀取 json,重寫方法 deserialize,示例如下:
清單 13 . 自定義序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
JsonParser 提供很多方法來讀取 json 資訊, 如 isClosed(), nextToken(), getValueAsString()等。若想單獨建立 JsonParser,可以通過 JsonFactory() 的 createParser。
- 定義好自定義序列化類和自定義反序列化類,若想在程式中呼叫它們,還需要註冊到 ObjectMapper 的 Module,示例如下:
清單 14 . 注 冊 M odule 示例
1 2 3 4 5 6 7 8 |
|
樹模型處理
Jackson 也提供了樹模型(tree model)來生成和解析 json。若想修改或訪問 json 部分屬性,樹模型是不錯的選擇。樹模型由 JsonNode 節點組成。程式中常常使用 ObjectNode,ObjectNode 繼承於 JsonNode,示例如下:
清單 15 . ObjectNode 生成和解析 json 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|