【Kotlin/Android】GSONでTypeAdapterを使ってJSONの値を別のデータ型に変換する方法
この記事からわかること
- Android Studio/Kotlinのライブラリ:GSONの使い方
- fromJson/toJsonメソッドの使い方
- TypeAdapterで値を任意のデータ型に変換するには?
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
参考文献:公式リファレンス:GSON
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
GSONでJSONの値を別のデータ型に変換する方法
例えば値として0
または1
を持つJSONの形式があった場合にこれをKotlin内ではBoolean
として扱いたいとします。今回使用するJSON変換ライブラリGSONでは普通に変換するとInt
型になってしまうのでこれをカスタムできるように実装していきます。
JSON
{
"id": "12345",
"flag": 1
}
Kotlinで扱いたいクラス
data class Example(
val id: String,
val flag: Boolean
)
TypeAdapterを使用する
GSONでJSONの値を別のデータ型に変換するにはTypeAdapter
を継承したExample
を変換するためのカスタムクラスを用意します。
- writeメソッド:オブジェクトをJSONにエンコードする方法を定義
- readメソッド:JSONをオブジェクトにデコードする方法を定義
class ExampleTypeAdapter : TypeAdapter<Example>() {
/** オブジェクトをJSONにエンコードする方法を定義 */
override fun write(out: JsonWriter, value: Example) {
// オブジェクトのエンコード開始
out.beginObject()
out.name("id").value(value.id)
out.name("flag").value(if (value.flag) 1 else 0)
// オブジェクトのエンコード終了
out.endObject()
}
/** JSONをオブジェクトにデコードする方法を定義 */
override fun read(`in`: JsonReader): Example {
var id: String? = null
var flag: Boolean? = null
// オブジェクトのデコード開始
`in`.beginObject()
// hasNext:未処理のデータがあるか
while (`in`.hasNext()) {
// nextName():キー名を取得
when (`in`.nextName()) {
// nextString():Stringとして読み取り
"id" -> id = `in`.nextString()
"flag" -> {
// peek():JSONの値を取得
flag = when (`in`.peek()) {
// データ型によって分岐(念の為複数パターン用意)
// Int → 0でない場合はtrue、0の場合はfalse
JsonToken.NUMBER -> `in`.nextInt() != 0
// Boolean → そのまま
JsonToken.BOOLEAN -> `in`.nextBoolean()
// String → 文字列が "true"であるかどうかを確認
JsonToken.STRING -> {
val stringValue = `in`.nextString()
stringValue.equals("true", ignoreCase = true)
}
else -> throw IllegalStateException("期待する値ではなかったよ:" + `in`.peek())
}
}
// その他のキーはスキップ
else -> `in`.skipValue()
}
}
// オブジェクトのデコード終了
`in`.endObject()
return Example(
id = id ?: throw IllegalStateException("Missing 'id' field in JSON"),
flag = flag ?: throw IllegalStateException("Missing 'flag' field in JSON")
)
}
}
続いて作成したTypeAdapter
クラスはregisterTypeAdapter
を使用して登録しておきます。
val gson: Gson = GsonBuilder()
.registerTypeAdapter(Example::class.java, ExampleTypeAdapter())
.create()
あとはGSONを使用して普通にエンコード/デコード処理を実装すれば期待通りの結果になります。
val jsonString = """{"id":"12345","flag":1}"""
val example: Example = gson.fromJson(jsonString, Example::class.java)
Log.d("GSON", example.flag.toString()) // true
val jsonStringFalse = """{"id":"23456","flag":0}"""
val exampleFalse: Example = gson.fromJson(jsonStringFalse, Example::class.java)
Log.d("GSON", exampleFalse.flag.toString()) // false
val json = gson.toJson(example)
Log.d("GSON", json) // {"id":"12345","flag":1}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。