🤖

moshiとは?

2024/12/08に公開

Moshi ドキュメント

概要

Moshiは、KotlinとJavaのためのモダンなJSONライブラリです。GsonやJacksonの代替として使用でき、特にKotlinとの相性が優れています。

主な特徴

  • Kotlinのデータクラスとの優れた統合
  • NullセーフティとJSONの型安全な変換
  • カスタマイズ可能なアダプター機能
  • 軽量で高速な処理
  • AndroidプロジェクトでのProguard対応

セットアップ

Gradle依存関係の追加

dependencies {
    implementation("com.squareup.moshi:moshi:1.15.0")
    implementation("com.squareup.moshi:moshi-kotlin:1.15.0")
    // コードジェネレーション用(推奨)
    ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0")
}

基本的な使い方

データクラスの定義

@JsonClass(generateAdapter = true)
data class User(
    val id: Int,
    val name: String,
    @Json(name = "email_address") val email: String,
    val age: Int?
)

Moshiインスタンスの作成

val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

JSONの変換(シリアライズ/デシリアライズ)

// アダプターの取得
val adapter = moshi.adapter<User>()

// オブジェクトからJSONへの変換(シリアライズ)
val user = User(1, "山田太郎", "yamada@example.com", 30)
val json = adapter.toJson(user)

// JSONからオブジェクトへの変換(デシリアライズ)
val parsedUser = adapter.fromJson(json)

高度な使い方

カスタムアダプターの作成

特殊な型やフォーマットを扱う場合、カスタムアダプターを作成できます:

class DateAdapter {
    @FromJson
    fun fromJson(value: String): Date {
        return SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(value)
    }

    @ToJson
    fun toJson(date: Date): String {
        return SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(date)
    }
}

Nullableな値の処理

Moshiは、KotlinのNull安全性を尊重します:

@JsonClass(generateAdapter = true)
data class Message(
    val title: String,           // 必須フィールド
    val description: String?,    // オプショナルフィールド
    val timestamp: Long = 0      // デフォルト値を持つフィールド
)

コレクションの処理

リストやマップなどのコレクションも自然に扱えます:

@JsonClass(generateAdapter = true)
data class BlogPost(
    val title: String,
    val tags: List<String>,
    val metadata: Map<String, String>
)

ベストプラクティス

  1. コードジェネレーションの使用

    • @JsonClass(generateAdapter = true) アノテーションを使用して、パフォーマンスを最適化
  2. 適切なNull処理

    • 必須フィールドとオプショナルフィールドを明確に区別
    • デフォルト値の活用
  3. カスタムネーミング

    • @Json(name = "server_field_name") でサーバー側の命名規則に対応
  4. エラーハンドリング

try {
    val user = adapter.fromJson(json)
} catch (e: JsonDataException) {
    // JSONデータの形式が不正な場合の処理
} catch (e: JsonEncodingException) {
    // JSONのエンコーディングが不正な場合の処理
}

主な注意点

  1. 循環参照の回避

    • 循環参照を含むデータ構造は、スタックオーバーフローを引き起こす可能性があります
  2. 大きなJSONの処理

    • 大量のデータを扱う場合は、ストリーミングAPIの使用を検討
  3. プロガード設定

    • Androidプロジェクトでは、適切なProguardルールの設定が必要
-keep class com.squareup.moshi.** { *; }
-keep @com.squareup.moshi.JsonQualifier interface *
-keepclassmembers class * {
    @com.squareup.moshi.FromJson *;
    @com.squareup.moshi.ToJson *;
}

トラブルシューティング

よくある問題と解決方法

  1. コンパイルエラー

    • KSP(Kotlin Symbol Processing)プラグインが正しく設定されているか確認
    • アノテーションプロセッシングが有効になっているか確認
  2. ランタイムエラー

    • JsonDataException: JSONの構造がデータクラスと一致しているか確認
    • 必須フィールドにnullが含まれていないか確認
  3. パフォーマンスの問題

    • アダプターのインスタンスを再利用しているか確認
    • 大きなJSONを処理する場合はストリーミングAPIの使用を検討

参考リンク

Discussion