daisuzz.log

kotlinx-serializationに触れてみた

今回はkotlinx.serializationというライブラリを触ってみます。

github.com

kotlinx.serialiationはリフレクションを利用せずにシリアライズ/デシリアライズを行うことができるライブラリで、JSONやCBORやProtobufをサポートしているようです。 今回は、公式のREADMEを参考にdata classからjsonへのシリアライズjsonからdata classへのデシリアライズ処理を試していきたいと思います。 サンプルコードはこちら。

やっていることは公式と変わらないので、詳細は公式のREADMEを参考にしてください。

環境

Kotlin 1.3.30, Gradle 4.10.2, kotlinx-serialization-runtime 0.11.0

導入

まずは、build.gradle.ktsに設定を追加していきます。

buildscript {
    repositories {
        jcenter()
    }

    val kotlinVersion = "1.3.30"

    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
        classpath("org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion")
    }
}

plugins{
    kotlin("jvm") version "1.3.30"
    id("kotlinx-serialization") version "1.3.30"
}

...

repositories {
    jcenter()
    maven{setUrl("https://kotlin.bintray.com/kotlinx")}
}

dependencies {
    implementation(kotlin("stdlib-jdk8"))
    implementation("org.jetbrains.kotlin:kotlin-stdlib:1.3.30")
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0")
}

plugins{}を利用する場合、Gradle plugin portalにkotlinx-serializationがまだpublishされていないため、settings.gradleに以下を追加します。

pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "kotlin-multiplatform") {
                useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
            }
            if (requested.id.id == "kotlinx-serialization") {
                useModule("org.jetbrains.kotlin:kotlin-serialization:${requested.version}")
            }
        }
    }
}

サンプルコード

まず、Personというdata classを用意します。シリアライズ/デシリアライズを行うために@Serializableをクラスに付与する必要があります。

import kotlinx.serialization.Serializable

@Serializable
data class Person(
    private val firstName: String = "Ieyasu",
    private val lastName: String = "Tokugawa",
    private val age: Int = 20
)

次に実際にシリアライズ/デシリアライズ処理を書いていきます。

import kotlinx.serialization.json.Json
import kotlinx.serialization.list

fun main() {

    val jsonData = Json.stringify(Person.serializer(), Person())
    val jsonList = Json.stringify(Person.serializer().list, listOf(Person(), Person("Hideyoshi", "Toyotomi")))
    println(jsonData)
    println(jsonList)

    val oda20 = Json.parse(Person.serializer(), """{"firstName":"Nobunaga", "lastName":"Oda", "age":20}""")
    val oda30 = Json.unquoted.parse(Person.serializer(), """{firstName:Nobunaga, lastName:Oda, age:30}""")
    println(oda20)
    println(oda30)
}

このコードを実際に実行してみると、以下のように出力されます。 Json.stringify()シリアライズを行い、Json.parse(), でデシリアライズされていることがわかります。ちなみにJson.unquotedとすると、クオーテションを無視してシリアライズ/デシリアライズ処理が行われます。

...
{"firstName":"Ieyasu","lastName":"Tokugawa","age":20}
[{"firstName":"Ieyasu","lastName":"Tokugawa","age":20},{"firstName":"Hideyoshi","lastName":"Toyotomi","age":20}]
Person(firstName=Nobunaga, lastName=Oda, age=20)
Person(firstName=Nobunaga, lastName=Oda, age=20)
...

おわりに

今回はkotlinx-serializationを触ってみました。リフレクションを使わない分、moshiやgsonなどに比べて処理が早くなると言われているので、実際に処理時間を比べてみるのも面白いと思いました。おしまい。