やったこととか思ったこと

やったことを忘れないように気が向いたら書きます

spray-jsonでケースクラスをトレイトでシリアライズ・デシリアライズする

spray-jsonでケースクラスをトレイトでシリアライズ・デシリアライズしようと思ったときに悩んだのでメモ。

trait Animal
case class Cat(name: String) extends Animal // Animalで変換したい

こんな感じのを変換したい場合

import spray.json._
import DefaultJsonProtocol._

trait Animal
case class Cat(name: String, kind: String = "cat") extends Animal

implicit val CatFormat = jsonFormat2(Cat)
implicit object AnimalFormat extends RootJsonFormat[Animal] {
  def write(obj: Animal): JsValue = obj match {
    case cat: Cat => cat.toJson
  }
  def read(json: JsValue): Animal = json.asJsObject.fields("kind") match {
    case JsString("cat") => json.convertTo[Cat]
  }
}
 
val animal: Animal = Cat("tama")
val json = animal.toJson
val animal2 = json.convertTo[Animal]

println(animal)  // Cat(tama,cat)
println(json)    // {"kind":"cat","name":"tama"}
println(animal2) // Cat(tama,cat)

こうすればできる
AnimalFormatオブジェクトのreadメソッドのjson.asJsObject.fields("kind")の部分は最初に見つけたのを使っているだけなのでもっといいやり方があるかもしれないです。