Kotlin の Serialization の JSON を Kotlin Script で使う方法を調べた。
注意点としては、 スクリプト実行時に -Xplugin オプションを追加する必要がある。
see also: https://stackoverflow.com/questions/68202117/how-do-i-apply-a-plugin-in-a-kts-kotlin-script-file
$ kotlin -version
Kotlin version 1.9.22-release-704 (JRE 17.0.10+7-Ubuntu-122.04.1)
まずはウォーミングアップとして。
json.main.kts
@file:Repository("https://repo1.maven.org/maven2/")
@file:DependsOn("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.3")
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.jsonObject
val jsonString = """{
"pokemons": [
{"name": "Pikachu", "type": "Electric"},
{"name": "Raichu", "type": "Electric"},
{"name": "Squirtle","type": "Water"}]}"""
val rootElement: JsonElement = Json.parseToJsonElement(jsonString)
val pokemons: JsonArray = rootElement.jsonObject["pokemons"] as JsonArray
pokemons.forEach { pokemon->
val name = pokemon.jsonObject["name"]
val type = pokemon.jsonObject["type"]
println("- $name ($type)")
}
実行します。
$ kotlin json.main.kts
- "Pikachu" ("Electric")
- "Raichu" ("Electric")
- "Squirtle" ("Water")
できました。
JSONを用意したデータクラスへ変換します。 (デコード, デシリアライズ?またはインフレートすると言うべきか。) そのためのデータクラス Pokemon と Pokemons を用意。
import kotlinx.serialization.Serializable
@Serializable
data class Pokemon(val name: String, val type: String)
@Serializable
data class Pokemons(val pokemons: List<Pokemon>)
さらに decodeFromString で jsonString を Pokemons へ変換するコードを追加。 ( decodeFromString をインポートしておく必要があります。)
import kotlinx.serialization.decodeFromString
val pokemons = Json.decodeFromString<Pokemons>(jsonString)
println(pokemons)
実行します。
$ kotlin -Xplugin=$HOME/.local/kotlinc/lib/kotlinx-serialization-compiler-plugin.jar json.main.kts
Pokemons(pokemons=[Pokemon(name=Pikachu, type=Electric), Pokemon(name=Raichu, type=Electric), Pokemon(name=Squirtle, type=Water)])
-Xplugin で指定するパス:
$HOME/.local/kotlinc/lib/kotlinx-serialization-compiler-plugin.jar
は環境に合わせて変更してください。
実際のところ、この手順で作業したときに、(事情はよくわからないのだが、おそらくキャッシュしているとかかな?) 一回目はうまく動かない。 @Serialization のアノテーションをいったんはコメントアウトして実行して(当然エラーになる)、 再度コメントアウト外して実行したら作動しました。
これはいやな感じです。 スクリプトで Serialization するのは避けた方がよいかもしれません。 素直に Gradle のプロジェクトをつくるべきか。
完成したコード json.main.kts:
@file:Repository("https://repo1.maven.org/maven2/")
@file:DependsOn("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.3")
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
@Serializable
data class Pokemon(val name: String, val type: String)
@Serializable
data class Pokemons(val pokemons: List<Pokemon>)
val jsonString = """{
"pokemons": [
{"name": "Pikachu", "type": "Electric"},
{"name": "Raichu", "type": "Electric"},
{"name": "Squirtle","type": "Water"}]}"""
/*
val rootElement: JsonElement = Json.parseToJsonElement(jsonString)
val pokemons: JsonArray = rootElement.jsonObject["pokemons"] as JsonArray
pokemons.forEach { pokemon->
val name = pokemon.jsonObject["name"]
val type = pokemon.jsonObject["type"]
println("- $name ($type)")
}
*/
val pokemons = Json.decodeFromString<Pokemons>(jsonString)
println(pokemons)