kotlinx.serialization のこと
kotlinx.serialization は、kotlin 用のシリアライゼーションライブラリである。 gradle のプラグインが提供されていて、@Serializable アノテーションがついているクラスに対するシリアライザを生成してくれる。 プラグインのソースコードは https://github.com/JetBrains/kotlin/tree/master/plugins/kotlinx-serialization にある。なにかコード生成ライブラリ使ってるのかと思ったら kotlin そのものの機能を使ってそう。
kotlinx.serialization のドキュメントは以下の場所にある。Polymorphism のような機能があって Jackson に出来ることは一通りできそう。 https://github.com/Kotlin/kotlinx.serialization/blob/4bf4113c2c6936e841caf2a8670382e701e7fcc2/docs/serialization-guide.md
たとえば以下のように使うのだが、、
package org.example
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@Serializable
data class Greeting(val greeting: String)
fun main() {
println("Hello World!")
println(Json.encodeToString(Greeting("Hello, Kotlin/JS!")))
}
生成されるコードは以下のようになっている。Greeting$serializer.serialize
が生成されてるので、実行時には高速に処理ができそうだ。
(kotlin のデコンパイルを IDEA がサポートしてほしいなぁと思いつつ幾星霜)
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package org.example
@kotlinx.serialization.Serializable public final data class Greeting public constructor(greeting: kotlin.String) {
public companion object {
public final fun serializer(): kotlinx.serialization.KSerializer<org.example.Greeting> { /* compiled code */ }
}
internal constructor(seen0: kotlin.Int, greeting: kotlin.String?, serializationConstructorMarker: kotlinx.serialization.internal.SerializationConstructorMarker?) { /* compiled code */ }
public final val greeting: kotlin.String /* compiled code */
public final operator fun component1(): kotlin.String { /* compiled code */ }
public open operator fun equals(other: kotlin.Any?): kotlin.Boolean { /* compiled code */ }
public open fun hashCode(): kotlin.Int { /* compiled code */ }
public open fun toString(): kotlin.String { /* compiled code */ }
@kotlin.jvm.JvmStatic internal final fun `write$Self`(self: org.example.Greeting, output: kotlinx.serialization.encoding.CompositeEncoder, serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit { /* compiled code */ }
@kotlin.Deprecated public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer<org.example.Greeting> {
public final val descriptor: kotlinx.serialization.descriptors.SerialDescriptor /* compiled code */
public final fun childSerializers(): kotlin.Array<kotlinx.serialization.KSerializer<*>> { /* compiled code */ }
public final fun deserialize(decoder: kotlinx.serialization.encoding.Decoder): org.example.Greeting { /* compiled code */ }
public final fun serialize(encoder: kotlinx.serialization.encoding.Encoder, value: org.example.Greeting): kotlin.Unit { /* compiled code */ }
}
}
さて、実際速度的にはどうなのかな? というのが気になりますよね。 kotlinx.serialization のレポジトリ、ちゃんとベンチマークコードが入っているのに、結果をのせてないところが奥ゆかしいですね。 https://github.com/Kotlin/kotlinx.serialization/blob/4bf4113c2c6936e841caf2a8670382e701e7fcc2/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt
./gradlew jmh
とかすれば、結果が得られるので、手元で動かして結果を見てみると良さそう。
Benchmark Mode Cnt Score Error Units
JacksonComparisonBenchmark.jacksonFromString thrpt 10 731.704 ± 17.971 ops/ms
JacksonComparisonBenchmark.jacksonSmallToString thrpt 10 9779.674 ± 3045.866 ops/ms
JacksonComparisonBenchmark.jacksonToString thrpt 10 1811.471 ± 55.360 ops/ms
JacksonComparisonBenchmark.jacksonToStringWithEscapes thrpt 10 1508.877 ± 122.538 ops/ms
JacksonComparisonBenchmark.kotlinFromStream thrpt 10 1080.475 ± 82.937 ops/ms
JacksonComparisonBenchmark.kotlinFromString thrpt 10 1375.436 ± 89.197 ops/ms
JacksonComparisonBenchmark.kotlinSmallToOkio thrpt 10 8141.993 ± 111.842 ops/ms
JacksonComparisonBenchmark.kotlinSmallToStream thrpt 10 10325.260 ± 2784.316 ops/ms
JacksonComparisonBenchmark.kotlinSmallToString thrpt 10 10832.368 ± 306.662 ops/ms
JacksonComparisonBenchmark.kotlinToOkio thrpt 10 898.711 ± 26.997 ops/ms
JacksonComparisonBenchmark.kotlinToStream thrpt 10 1011.233 ± 62.126 ops/ms
JacksonComparisonBenchmark.kotlinToString thrpt 10 1912.123 ± 192.133 ops/ms
JacksonComparisonBenchmark.kotlinToStringWithEscapes thrpt 10 1336.079 ± 303.871 ops/ms
結果はこんな感じになる。 chatgpt で markdown に整形した結果が以下。そんなにすごい差があるわけでもない。