厄介なクラッシュデータモデルを構築し、APIレスポンスを処理するために kotlinx.serialization を統合したとします。すべてが完璧に見えますが、Json.decodeFromString<User>(jsonString) を実行した瞬間に問題が発生します。アプリはオブジェクトを生成する代わりに、次の例外をスローして停止します。
kotlinx.serialization.SerializationException: Serializer for class 'User' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
このエラーは通常、ライブラリが生成されたはずの $serializer コンパニオンオブジェクトを探しても見つからない実行時に発生します。また、ビルド環境が Kotlin コンパイラと正しく通信できていない場合、コンパイル時に発生することもあります。
なぜ Kotlinx Serialization は特別なのかGson や Jackson のような従来のライブラリは、アプリの実行中にリフレクションを使用してクラスの内部を調査します。しかし、Kotlinx Serialization は異なるアプローチを取ります。これはコンパイラベースのエンジンです。APK のビルド中にシリアライズロジックを生成するため、特定の Kotlin コンパイラプラグインに依存しています。そのプラグインが有効でない場合、@Serializable アノテーションはライブラリに無視される単なる装飾的なコメントに過ぎません。
ほとんどの開発者がこの問題に直面する理由は、主に次の4つのいずれかです。
- Gradle に
kotlinx-serializationコンパイラプラグインが追加されていない。- ネストされたデータクラスに@Serializableアノテーションを付け忘れている。- R8 (ProGuard) がリリースビルドで生成されたコードを削除してしまった。- Kotlin のバージョン(例:1.9.20)と serialization ライブラリのバージョン(例:1.6.0)に不一致がある。## ステップバイステップの修正方法### 1. コンパイラプラグインを適用するランタイムの依存関係(implementationの行)を追加するだけでは不十分です。Kotlin コンパイラに対して、追加のコードを生成するように指示する必要があります。アプリレベルのbuild.gradleファイルを開き、プラグインが登録されていることを確認してください。 Groovy の場合 (build.gradle):
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
// 不足している重要なピース:
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.22'
}
Kotlin DSL の場合 (build.gradle.kts):
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
// このバージョンをプロジェクトの Kotlin バージョンに合わせてください
kotlin("plugin.serialization") version "1.9.22"
}
2. アノテーションを再確認するシリアライズのチェーンに含まれるすべてのクラスにアノテーションが必要です。もし User クラスが Address クラスを含んでいるなら、両方にマークを付ける必要があります。これは、複雑でネストされた JSON ツリーを扱う際によくある見落としです。
import kotlinx.serialization.Serializable
@Serializable
data class User(
val id: Int,
val name: String,
val location: Address // Address も @Serializable である必要があります!
)
3. リリースビルド用に R8 を設定するデバッグモードでは動作するのに、リリースモードでクラッシュしませんか?それは典型的な R8 の問題です。シュリンカーが生成された $serializer クラスを「未使用」と判断し、サイズ削減のために削除してしまうのです。これらのクラスを保持するように設定する必要があります。
proguard-rules.pro ファイルに以下のルールを追加してください。
# アノテーションが付いたクラスの Serializer ロジックを保持する
-keepclassmembernames class * {
@kotlinx.serialization.Serializable *;
}
# R8 が生成された $serializer を削除するのを防ぐ
-keepclassnames class kotlinx.serialization.internal.** { *; }
-keepclassmembers class * extends kotlinx.serialization.KSerializer {
public static ** INSTANCE;
}
デバッグのプロのヒントコードの変更に取り掛かる前に、必ず JSON ソースを検証してください。カンマが1つ抜けていたり、非 null フィールドに null 値が入っていたりするだけで、紛らわしいエラーが発生することがあります。私は ToolCraft の JSON Formatter & Validator を使って生の API 文字列をチェックしています。これにより、「Serializer not found」メッセージの背後に隠れている構造的な不一致を素早く特定できます。
マルチモジュールプロジェクトで作業している場合、kotlin-serialization プラグインは継承されないことに注意してください。@Serializable クラスを含むすべてのモジュールにプラグインを適用する必要があります。もしモジュール A がモジュール B のデータクラスを使用しており、モジュール B にプラグインが適用されていない場合、アプリは実行時にクラッシュします。
最終確認修正が確実に行われたか確認するために、次の3つの手順を実行してください。
- Clean Project を実行してから Rebuild Project を実行します。これにより、コンパイラプラグインが強制的に再実行されます。- まずデバッグモードで
Json.decodeFromStringの呼び出しをテストします。- リリース APK をビルドし、実機でテストします。これにより、ProGuard ルールが実際に機能していることが確認できます。

