はじめに
通信処理とかで JSON をパースする際に GSON 使ってたんですが Kotlin Serialization ってのがあるらしいです。
使い方もすごく簡単だし Kotlin で JSON を扱う場合はこれを使いましょう!
公式リポジトリ
Kotlin/kotlinx.serialization
導入方法
-
プロジェクトの build.gradle に下記を追加
1234dependencies {// これ追加classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"} -
モジュールの build.gradle に下記を追加
123456789plugins {// これ追加id 'kotlinx-serialization'}dependencies {// これ追加implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1'}
使い方
使い方はめっちゃ簡単!下記のように @Serializable
をつけるだけ!
1 2 3 4 5 6 7 8 9 10 11 12 |
@Serializable data class Hoge( val text: String, val num: Int, val flag: Boolean, ) val hogeJson = """ {"text": "hoge", "num": 3, "flag": true} """ val hoge = Json.decodeFromString<Hoge>(hogeJson) println(hoge) // Hoge(text=hoge, num=3, flag=true) |
Retrofit を使った通信の場合
Retorfit を使った通信でレスポンスをパースする場合は下記のようにします。
-
モジュールの build.gradle の dependencies に下記を追加
1implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0' -
Retrofit.Builder で Converter を指定
1234val retrofit = Retrofit.Builder().addConverterFactory(Json{ ignoreUnknownKeys = true }.asConverterFactory(MediaType.get("application/json"))).baseUrl("https://example.com").build()
これでレスポンスをパースできるようになります。
色々なJSON
オプショナル
下記のように JSON に num のキーが存在しない場合このままではエラーになります。
kotlinx.serialization.MissingFieldException: Field 'num' is required, but it was missing
1 2 3 4 5 6 7 8 9 10 11 |
@Serializable data class Hoge( val text: String, val num: Int, val flag: Boolean, ) val hogeJson = """ {"text": "hoge", "flag": true} """ val hoge = Json.decodeFromString<Hoge>(hogeJson) // エラー |
下記のようにデフォルト値を設定すればいいようです。(Optional アノテーションはなくなったのかな??)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// デフォルト値を設定 @Serializable data class Hoge( val text: String, val num: Int = 0, val flag: Boolean, ) // nullにしたければこう @Serializable data class Fuga( val text: String, val num: Int? = null, val flag: Boolean, ) |
ただデフォルト値はエンコード時に無視されるらしい。。。
1 2 |
val hoge = Hoge("hoge", flag = true) println(Json.encodeToString(hoge)) // {"text":"hoge","flag":true} |
プロパティ名とキー名が違う場合
下記のように JSON のキーと異なるプロパティ名にしたい場合は SerialName アノテーションを使います。
1 2 3 4 5 6 7 8 9 10 11 12 |
@Serializable data class Hoge( @SerialName("hoge_name") val hogeName: String, val num: Int, ) val hogeJson = """ {"hoge_name": "hoge", "num": 10} """ val hoge = Json.decodeFromString<Hoge>(hogeJson) println(hoge) // Hoge(hogeName)=hoge, num=10) |
入れ子
Serializable アノテーションをつけたクラスのプロパティに Serializable アノテーションをつけたクラスを利用することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Serializable data class Hoge( val text: String, val fuga: Fuga, ) @Serializable data class Fuga( val text: String, ) val hogeJson = """ {"text": "hoge", "fuga": {"text": "fuga"}} """ val hoge = Json.decodeFromString<Hoge>(hogeJson) println(hoge) // Hoge(text=hoge, fuga=Fuga(text=fuga)) |
下記のようにリストもあつかえます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Serializable data class Hoge( val text: String, @SerialName("fuga") val fugaList: List<Fuga>, ) @Serializable data class Fuga( val text: String, ) val hogeJson = """ {"text": "hoge", "fuga": [{"text": "fuga1"}, {"text": "fuga2"}]} """ val hoge = Json.decodeFromString<Hoge>(hogeJson) println(hoge) // Hoge(text=hoge, fugaList=[Fuga(text=fuga1), Fuga(text=fuga2)]) |
おわりに
これでざっくり使い方はわかりました! Swift の Codable みたいに使えてとっつきやすいです!!
ちょっと残念なのが個人的によく使っていた JSONExport は Kotlin Serialization には対応してないみたいです。。。
複雑な JSON はまた出会ったときに考えます!
コメント