■ はじめに
https://dk521123.hatenablog.com/entry/2023/03/16/012034
で、ScalaでYAMLファイルを扱ったが、 今回は、JSONについて、調べた。
目次
【0】Scala で JSON 補足:scala.util.parsing.json.JSON 【1】Gson 1)インストール 2)サンプル 【2】Json4s 1)インストール 2)サンプル 【3】spray-json 1)インストール 2)サンプル 【4】circe 1)インストール 2)サンプル 【5】その他のライブラリ 1)argonaut 2)uPickle / uJSON 3)sjson
【0】Scala で JSON
Scala2.12以降では、外部ライブラリを使う必要がありそう。
補足:scala.util.parsing.json.JSON
* version 1.0.6より前は、 scala.util.parsing.json.JSON があったが 現在では非推奨になっている(Scala2.12だと、もうない?)
https://www.scala-lang.org/api/2.12.6/scala-parser-combinators/scala/util/parsing/json/JSON$.html
より抜粋 ~~~~ Deprecated (Since version 1.0.6) Use The Scala Library Index to find alternatives: https://index.scala-lang.org/ ~~~~
【1】Gson
* Google 製の JSONライブラリ
https://dzone.com/articles/lets-unblock-read-json-using-gson-in-scala
1)インストール
libraryDependencies ++= Seq( "com.google.code.gson" % "gson" % "2.10.1",
https://mvnrepository.com/artifact/com.google.code.gson/gson
2)サンプル
import com.google.gson.{Gson, JsonObject} case class Person(name: String, sex: String, age: Int) object Main extends App { val gson = new Gson val source = """{ "name": "Mike", "age": 17 }""" // Serializing the Json String to the Person Object in Scala. val result = gson.fromJson(source, classOf[Person]) println(result) println(result.name) println(result.sex) // null println(result.age) }
【2】Json4s
* 個人的には、これがいいと思う。 * 詳細は、以下を参照
https://www.qoosky.io/techs/aba44d3e38
和訳
https://gist.github.com/takungsk/4025974
1)インストール
libraryDependencies ++= Seq( "org.json4s" %% "json4s-jackson" % "4.1.0-M2",
2)サンプル
import org.json4s._ import org.json4s.jackson.JsonMethods._ object Main extends App { val json1 = """{ "numbers" : [1, 2, 3, 4, 5] }""" val json1Values = parse(json1) val map1Values = json1Values.asInstanceOf[JObject].values println(map1Values) //=> Map(numbers -> List(1, 2, 3, 4, 5)) println(map1Values.get("numbers")) //=> Some(List(1, 2, 3, 4, 5)) val json2 = """{ "name" : "Mike", "age" : 24 }""" val json2Values = parse(json2) val map2Values = json2Values.asInstanceOf[JObject].values println(map2Values) //=> Map(name -> Mike, price -> 24) println(map2Values.get("age")) //=> Some(24) }
【3】spray-json
* Latest「Nov 11, 2020」で 2年半近くメンテされていないのがデメリット、、、
https://riptutorial.com/scala/example/7718/json-with-spray-json
https://qiita.com/takutoki/items/03cdbf698c51123ac606
1)インストール
https://github.com/spray/spray-json
build.sbt
// インストール libraryDependencies ++= Seq( "io.spray" %% "spray-json" % "1.3.6",
2)サンプル
例1:Mapへの変換
import spray.json._ import DefaultJsonProtocol._ object Main extends App { val res = """{ "hello": "World!!" }""".parseJson val results = res.convertTo[Map[String, String]] println(s"results = ${results}") println(s"results.get(hello) = ${results.get("hello").get}") println("Done...") }
例2:クラスへの変換
import spray.json._ case class Person(name: String, age: Int) object DemoJsonProtocol extends DefaultJsonProtocol { // jsonFormatX (X: フィールドの数に対応.今回、Personは name/age の2) implicit val personFormat = jsonFormat2(Person) } import DemoJsonProtocol._ object Main extends App { val source = """{ "name": "Mike", "age": 17 }""".parseJson val json = source.convertTo[Person] println(s"json = ${json}") println(s"name = ${json.name}") println(s"age = ${json.age}") println("Done...") }
例2:クラスへの変換(remarksがOptional)
import spray.json._ case class Person(name: String, age: Int, remarks: String) object JsonPurserUtil { def int(value: JsValue, key: String): Option[Int] = value match { case JsObject(x) => x.get(key).flatMap(asInt) case _ => None } def asInt(value: JsValue): Option[Int] = value match { case JsNumber(x) if Int.MinValue <= x && x <= Int.MaxValue => Some(x.toInt) case _ => None } def str(value: JsValue, key: String): Option[String] = value match { case JsObject(x) => x.get(key).flatMap(asStr) case _ => None } def asStr(value: JsValue): Option[String] = value match { case JsString(x) => Some(x) case _ => None } } object PersonJsonProtocol extends DefaultJsonProtocol { // jsonFormatX (X: フィールドの数に対応.今回、Personは name/age/remarks の3) implicit object personJsonFormat extends RootJsonFormat[Person] { override def write(obj: Person): JsValue = Map( "name" -> obj.name.toJson, "age" -> obj.age.toJson, "remarks" -> obj.remarks.toJson ).toJson override def read(json: JsValue): Person = { val name = JsonPurserUtil.str(json, "name").getOrElse("") val age = JsonPurserUtil.int(json, "age").getOrElse(-1) val remarks = JsonPurserUtil.str(json, "remarks").getOrElse("") Person( name = name, age = age, remarks = remarks ) } } } import PersonJsonProtocol._ object Main extends App { val source = """{ "name": "Mike", "age": 17 }""".parseJson val json = source.convertTo[Person] println(s"json = ${json}") println(s"name = ${json.name}") println(s"age = ${json.age}") println(s"remarks = ${json.remarks}") println("Done...") }
【4】circe
* 詳細は、以下を参照
https://dev.classmethod.jp/articles/circe-first-guide/
1)インストール
build.sbt
// インストール val circeVersion = "0.14.1" libraryDependencies ++= Seq( "io.circe" %% "circe-core", "io.circe" %% "circe-generic", "io.circe" %% "circe-parser" ).map(_ % circeVersion)
2)サンプル
val jsonValue = """ |{ | "name": "Mike", | "email": "mike@demo.com" |} """.stripMargin // results の型:Either[io.circe.Error, Map[String, String]] val results = decode[Map[String, String]](jsonValue)
【5】その他のライブラリ
* 他にも色々ありそう、、、
1)argonaut
https://zenn.dev/110416/books/a94a86a2c696d1/viewer/810485
2)uPickle / uJSON
https://mungingdata.com/scala/read-write-json/
3)sjson
http://eed3si9n.com/ja/sjson-type-class-based-json/
関連記事
Scala ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/03/10/193805
Scala ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/12/184331
Scala ~ YAML ~
https://dk521123.hatenablog.com/entry/2023/03/16/012034
Scala ~ AWS SDK / Secrets Managerサンプル ~
https://dk521123.hatenablog.com/entry/2023/04/03/012600