今回は、Kotlin Serialization を使って JSON をパースする方法を解説します。
なお、ここに掲載しているソースコードは以下の環境で動作確認しています。
- Android Studio Bumblebee | 2021.1.1 Patch 2
- JDK 11.0.11
- Android Gradle Plugin 7.1.2
- Kotlin 1.6.20
- Gradle 7.4.2
- org.jetbrains.kotlin.plugin.serialization 1.6.20
- org.jetbrains.kotlinx:kotlinx-serialization-json 1.3.2
ライブラリのインポート
最初に、Kotlin Serialization を使用するために必要なライブラリをインポートします。
まず、以下のようにプロジェクトの build.gradle の plugins
に Kotlin Serialization のプラグインを追加します。
// Project's build.gradle plugins { id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.20' apply false }
そして、モジュールの build.gradle の plugins
にも Kotlin Serialization のプラグインを追加します。
// Module's build.gradle plugins { id 'org.jetbrains.kotlin.plugin.serialization' }
後は、モジュールの build.gradle の dependencies
に以下を追加します。
// Module's build.gradle dependencies { implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2" }
以上で、ライブラリのインポートは完了です。
データクラスの宣言
ここから、実装に入っていきます。
まず、パースする JSON のフォーマットをデータクラスで宣言する必要があります。今回は、以下のような JSON の読み書きを行ってみます。
{ "hidden_card": { "rank": "6", "suit": "SPADES" }, "visible_cards": [ { "rank": "4", "suit": "CLUBS" }, { "rank": "A", "suit": "HEARTS" } ] }
上記の JSON をデータクラスで宣言すると、以下のようになります。
@Serializable data class BlackjackHand( @SerialName("hidden_card") val hiddenCard: Card, @SerialName("visible_cards") val visibleCard: List<Card>, ) @Serializable data class Card( val rank: Char, val suit: Suit, ) enum class Suit { CLUBS, DIAMONDS, HEARTS, SPADES; }
Kotlin Serialization で使用するデータクラスには、@Serializable
を追加します。また、hidden_card
と hiddenCard
のように、JSON とデータクラスで名前が異なる場合、データクラスのプロパティに @SerialName
を付与して、対応する JSON の名前を指定します。なお、JSON とデータクラスで名前が一致する場合は、@SerialName
を省略できます。
以上で、データクラスの宣言は完了です。
JSON からオブジェクトにパースする
Json.decodeFromString
に JSON 文字列を渡すと、パースした後のオブジェクトを返してくれます。
val json = """ { "hidden_card": { "rank": "6", "suit": "SPADES" }, "visible_cards": [ { "rank": "4", "suit": "CLUBS" }, { "rank": "A", "suit": "HEARTS" } ] } """.trimIndent() Log.d(TAG, Json.decodeFromString<BlackjackHand>(json).toString())
上記を実行すると Logcat に以下のログが表示され、JSON からオブジェクトにパースが成功していることがわかります。
D/MainActivity: BlackjackHand(hiddenCard=Card(rank=6, suit=SPADES), visibleCard=[Card(rank=4, suit=CLUBS), Card(rank=A, suit=HEARTS)])
オブジェクトから JSON にパースする
逆に、Json.encodeToString
にオブジェクトを渡すと、パースした後の JSON を文字列で返してくれます。
val blackjackHand = BlackjackHand( Card('6', Suit.SPADES), listOf(Card('4', Suit.CLUBS), Card('A', Suit.HEARTS)) ) Log.d(TAG, Json.encodeToString(blackjackHand))
上記を実行すると Logcat に以下のログが表示され、オブジェクトから JSON にパースが成功していることがわかります。
D/MainActivity: {"hidden_card":{"rank":"6","suit":"SPADES"},"visible_cards":[{"rank":"4","suit":"CLUBS"},{"rank":"A","suit":"HEARTS"}]}