使用科特林序列化簡介

https://medium.com/@kezhang404/5bbfcf735aba

Kotlin Serialization 簡介

Kotlin Serialization 是由 Kotlin 提供的跨平台序列化和反序列化庫。它可以將物件樹序列化為數個常見格式,本身就原生支援 Kotlin,具有出色的可擴展性,幾乎能滿足所有業務場景需求。它無需使用反射,且性能出色,可謂當下 Kotlin 語言序列化工具的最佳選擇。

kotlinx.serialization 目前支援幾種格式:

在大多數情況下,我們使用 JSON,因此本文章將主要介紹 JSON 的使用。

Kotlin Serialization 分為兩個過程:第一步是將物件樹轉換為由基本數據類型組成的序列,第二步是根據格式編碼和輸出這個序列。

Integration

Kotlin Serialization 工具是一個獨立的組件,包括以下部分:

Gradle 編譯插件:org.jetbrains.kotlin.plugin.serialization

運行時依賴庫

首先需要在 Gradle 中添加編譯插件:

plugins {
id ‘org.jetbrains.kotlin.plugin.serialization’ version ‘1.9.23’
}

然後添加依賴庫:

dependencies {
implementation(“org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.2”)
implementation(“org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2”)
}

此外,kotlinx.serialization 有其自己的版本,與 Kotlin 的版本不同步。具體版本請參見此處。

JSON 編碼

將數據轉換為指定格式的過程稱為編碼。對於 Kotlin Serialization 編碼,可以使用擴展函數 Json.encodeToString。

@Serializable
class Project(val name: String, val language: String)

fun main() {
val data = Project(“kotlinx.serialization”, “Kotlin”)
println(Json.encodeToString(data))
}

Kotlin Serialization 不使用反射,因此要支持序列化/反序列化的類必須標記為 @Serializable 注解。

JSON 解碼

相反的過程稱為解碼。為了將 JSON 字串解碼為物件,我們將使用 Json.decodeFromString 擴展函數。為了指定我們想要獲取的結果類型,我們為此函數提供一個類型參數。

@Serializable
data class Project(val name: String, val language: String)

fun main() {
val data = Json.decodeFromString(“””
{“name”:”kotlinx.serialization”,”language”:”Kotlin”}
“””)
println(data)
}

@Serializable 注解

此注解用於標記可以被序列化的類,其序列化規則如下:

僅具有實體字段的屬性將參與序列化過程。代理屬性或具有 getter/setter 的屬性將不參與。

主構造函數中的參數必須是對象屬性。

對於需要在序列化完成之前進行數據驗證的情況,您可以在類的 init 块中驗證這些參數。

選填屬性

當將 JSON 字串反序列化為物件時,如果該 JSON 字串缺少了類中的某個屬性,則反序列化將失敗。不過,我們可以通過為該屬性添加一個默認值來避免此問題。

@Serializable
data class Project(val name: String, val language: String = “Kotlin”)

fun main() {
val data = Json.decodeFromString(“””
{“name”:”kotlinx.serialization”}
“””)
println(data)
}

@Required

@Required 注解表示使用該注解裝飾的屬性在反序列化過程中必須是非空的。

如果字段具有默認值且我們期望在反序列化過程中 JSON 輸入包含該字段,則可以使用此注解。使用後,如果該字段在 JSON 字串中不存在,則反序列化將失敗。

@Transient

如果一個屬性不需要被序列化,則可以使用 @Transient 注解來標記,並且該屬性必須具有默認值。

默認情況下,如果一個屬性類型是 @Transient 標記的,且反序列化的 JSON 字串中包含了與屬性相同名稱的屬性,則對這個屬性進行反序列化時會報錯。您可以在構建 Json 時使用 ignoreUnknownKeys = true 來避免錯誤。ignoreUnknownKeys 的含義是忽略序列化字串中的未知字段。默認情況下,它為 false,因此如果反序列化後的序列化字串包含了多餘的字段,反序列化將不會報錯。

默認值不參與序列化

如果一個屬性具有默認值,且該屬性在該物件中的值也是默認值,那麼這個值將不參與序列化。

@Serializable
data class User(val firstname: String, val lastname: String = “Zhang”)

fun main() {
val data = User(“Ke”)
println(Json.encodeToString(data))
// 輸出:{“firstname”:”Ke”}
}

如上所述,因為內建數據中的 language 屬性的值是默認值,序列化數據不包含 lastname。

如果為 lastname 設置了與默認值不相等的值,它將參與序列化。

fun main() {
val data = User(“Ke”, “Li”)
println(Json.encodeToString(data))
// 輸出:{“firstname”:”Ke”,”lastname”:”Li”}
}

當然,也有一種方式來規避這個問題。

@EncodeDefault

此注解是用來解決上述問題的,它可以使默認值也參與序列化。

此外,@EncodeDefault 注解可以使用 EncodeDefault.Mode 參數來調整其行為。

Serial field names

Kotlin Serialization 支持自定義屬性名稱的序列化和反序列化,這是通過 @SerialName 注解實現的。

Enum

Kotlin Serialization 支持 enum 類型,不需要在 enum 類型上使用 @Serializable 注解。

當然,如果您希望在序列化後自定義屬性名稱,也可以添加 @Serializable 注解並通過 @SerialName 進行設置。

預先存在的類型

除了支持基本類型和字符串外,Kotlin Serialization 也預先支持一些複合數據類型。

Pair

Triple

Array

List

Set

Map

Unit

Singleton Class

Duration

Nothing

Unit 和单例类的序列化/反序列化是相同的。因為 Unit 本身就是一个单例类,它的序列化包含一个空的 Json 字符串。

根據上述描述,Map 的序列化到 JSON 是以包含項目的 JSON 數組進行的:[key1, value1, key2, value2,…]。

其他

此外,Json 還提供了其他附加設置,適用於多樣的情境。

此外,Json 還提供了其他附加設置,適用於多樣的情境。

希望這次的整理能滿足您的需求。

via Android App Development on Medium

March 30, 2024 at 12:29AM

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *