play-jsonでReads/Writes/Formatを定義しなくてもよくする
play-jsonはReads/Writes/Formatを定義するのが面倒とよく言われるので、shapelessの練習も兼ねて作ってみました。
https://github.com/tototoshi/play-json-generic
scala> import play.api.libs.json._ import play.api.libs.json._ scala> case class Person(firstName: String, lastName: String, friends: List[Person]) defined class Person scala> val people = Person("John", | "Lennon", | List(Person("Paul", "McCartney", Nil), | Person("George", "Harrison", Nil), | Person("Ringo", "Starr", Nil))) people: Person = Person(John,Lennon,List(Person(Paul,McCartney,List()), Person(George,Harrison,List()), Person(Ringo,Starr,List()))) scala> Json.prettyPrint(Json.toJson(people)) <console>:18: error: No Json serializer found for type Person. Try to implement an implicit Writes or Format for this type. Json.prettyPrint(Json.toJson(people)) ^
Reads/Writes/Formatを定義していないcase classをシリアライズしようとすると当然こんなエラーが出ますが、
import com.github.tototoshi.play.json.generic._
することでシリアライズ/デシリアライズできるようになります。
scala> import com.github.tototoshi.play.json.generic._ import com.github.tototoshi.play.json.generic._ scala> Json.prettyPrint(Json.toJson(people)) res1: String = { "firstName" : "John", "lastName" : "Lennon", "friends" : [ { "firstName" : "Paul", "lastName" : "McCartney", "friends" : [ ] }, { "firstName" : "George", "lastName" : "Harrison", "friends" : [ ] }, { "firstName" : "Ringo", "lastName" : "Starr", "friends" : [ ] } ] } scala> Json.parse(res1).as[Person] res2: Person = Person(John,Lennon,List(Person(Paul,McCartney,List()), Person(George,Harrison,List()), Person(Ringo,Starr,List())))
play-jsonのJson.formatとかはマクロで実装されているので、そのマクロのためのオプションとかには一部対応できていないです。JsonNamingには対応できました。
Shapeless使ってみたいという人には The Type Astronaut's Guide to Shapeless - Underscore がすごくわかりやすくてオススメです。
追記
指摘されて気づいたんですが、HListを使っているので23個以上のフィールドを持つcase classにまつわる問題が解決しちゃってました。
https://github.com/tototoshi/play-json-generic/commit/0382c149efb4ed9fd4b4bcea99841641f2ca7949