iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Mobile Development

Kotlin 全面啟動 系列 第 17

[Kotlin 全面啟動] Serialization

  • 分享至 

  • xImage
  •  

這幾天我們介紹的 Coroutine、Flow 都是比較可以廣泛使用的工具,Kotlin 作為一個 general purpose programming language,在這方面的確是很強大,但 Kotlin 也是有很多 library 可以完成比較具體的任務的,比如說今天要介紹的 serialization。

Kotlinx Serialization 官網:
https://github.com/Kotlin/kotlinx.serialization

通常做網路傳輸或是儲存資料的時候,我們就會需要 serialization 來做序列化的動作把一個物件轉成可交換保存的 json 或 binary 形式,像是 Gson、Moshi 等 library 等都是很這方面很知名的工具,而在 KMM 的世界裡,則推薦直接使用 Kotlin 出的 kotlinx.serialization。

首先必須先加上 kotlinx.serialization 的 plugin 如下:

plugins {
    kotlin("jvm") version "1.7.10" // or kotlin("multiplatform") or any other kotlin plugin
    kotlin("plugin.serialization") version "1.7.10"
}

接下來就是要宣告 dependency 如下:

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0")
}

Serialization 的使用通常很單純,以 json 格式為例就只有把物件轉成 json 、跟把 json 轉成物件二種,一個簡單的範例如下:

import kotlinx.serialization.*
import kotlinx.serialization.json.*

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

fun main() {
    // Serializing objects
    val data = Project("kotlinx.serialization", "Kotlin")
    val string = Json.encodeToString(data)
    println(string) // {"name":"kotlinx.serialization","language":"Kotlin"}
    // Deserializing back into objects
    val obj = Json.decodeFromString<Project>(string)
    println(obj) // Project(name=kotlinx.serialization, language=Kotlin)
}

一般使用就是這麼簡單,但細心的讀者可能會發現有個淺規則要求 json 的 key 跟 object 的 name 要相同,但如果我們想要把二個不同的名字連結在一起的話怎麼辦呢?其實只要冠上 @SerialName 到你的變數前面,你就可以連結二個不同的元素再一起囉,改寫 Project 物件如下也是可以正常運作的:

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

Proguard

通常 serialization 的使用在 Android 裡都會需要在 proguard 做額外的設定,kotlinx.serialization 也不例外,目前建議的修改如下:

# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
    static <1>$Companion Companion;
}

# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
    static **$* *;
}
-keepclassmembers class <2>$<3> {
    kotlinx.serialization.KSerializer serializer(...);
}

# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
    public static ** INSTANCE;
}
-keepclassmembers class <1> {
    public static <1> INSTANCE;
    kotlinx.serialization.KSerializer serializer(...);
}

# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault

# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.
# If you have any, uncomment and replace classes with those containing named companion objects.
#-keepattributes InnerClasses # Needed for `getDeclaredClasses`.
#-if @kotlinx.serialization.Serializable class
#com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.
#com.example.myapplication.HasNamedCompanion2
#{
#    static **$* *;
#}
#-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.
#    static <1>$$serializer INSTANCE;
#}

Format

除了本篇介紹的 json 格式之外,其實 serialization 也支援以下幾種格式:

只是目前除了 json 外都是處於 experimental 的狀態,是否使用就靠讀者自行判斷囉!

https://github.com/Kotlin/kotlinx.serialization/blob/master/formats/README.md

講完了 serialization 接下來我們就可以開始進入網路傳輸的世界囉,明天見!


上一篇
[Kotlin 全面啟動] Flow II
下一篇
[Kotlin 全面啟動] Ktor Client
系列文
Kotlin 全面啟動 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言