次は、Json4sのJSON ASTからScalaのオブジェクトを生成する方法について解説。
Play-JSONでのScalaオブジェクト生成
Json4sのオブジェクト生成の前に、Play-JSONにおけるオブジェクト生成方法について見てみます。
import play.api.libs.json._ import play.api.libs.json.Reads._ case class Person(name: String, age: Int) object Main { def main(args: Array[String]): Unit = { implicit val PersonFormat = Json.format[Person] val source = """{ "name": "John", "age": 42 }""" val jsonAst = Json.parse(source) val result = jsonAst.validate[Person] result match { case s: JsSuccess[Person] => { val person: Person = s.get println(person) } case e: JsError => println(e) # prints 'Person(John,42)' } } }
ポイントは、implicit val PersonFormat = Json.format[Person]
という指定です。Play-JSONでは、case classのオブジェクトを生成するために、このような指定が必要になります。
Json4sでのScalaオブジェクト生成
では同じようにJson4sでオブジェクトを生成してみる。
import org.json4s._ import org.json4s.jackson.JsonMethods._ case class Person(name: String, age: Int) object Main { def main(args: Array[String]): Unit = { implicit val formats = DefaultFormats val source = """{ "name": "John", "age": 42 }""" val jsonAst = parse(source) val result = jsonAst.extract[Person] println(result) # prints 'Person(John,42)' } }
少し形式を変えて、case classではなく、通常のクラスとして定義してみます。
import org.json4s._ import org.json4s.jackson.JsonMethods._ class Person(val name: String, val age: Int) object Main { def main(args: Array[String]): Unit = { implicit val formats = DefaultFormats val source = """{ "name": "John", "age": 42 }""" val jsonAst = parse(source) val result = jsonAst.extract[Person] println(result.name) # prints "John" println(result.age) # prints "42" } }
unapply
メソッドが無いので、個別に出力していますが、case classでなくてもオブジェクトが得られていることが分かると思います。
一方で、Play-JSONでは通常のクラスに変更するとコンパイルエラーになります。No apply function found for example.Person
と、No Json deserializer found for type example.Person. Try to implement an implicit Reads or Format for this type.
というエラーが出ます。
これは他のScala用のJSONライブラリでも同様で、case classの場合は、コンパニオンオブジェクトを渡したり、予め利用するcase classの型を登録しておいたり、通常のクラスであれば、自前で変換方法を詳細に定義する必要があります。
しかし、Json4sではどれも必要ありません。
なぜでしょうか?
というところで次回に続きます。