3
votes

I'm using my own implicit implementation of JSON serializer and deserializer for my case object

My case class looks like (it's just a code snippet)

sealed trait MyTrait

case object MyCaseClass extends MyTrait

I want to write my own ser. and deser. of JSON for MyTrait

implicit val myTraitFormat = new JsonFormat[MyTrait] {
  override def read(json: JsValue): MyTrait = json.asJsObject.getFields("value") match {
    case Seq(JsString("TEST")) ⇒ MyCaseClass
    case _ ⇒ throw new DeserializationException(s"$json is not a valid extension of my trait")
  }
  override def write(myTrait: MyTrait): JsValue = {
    myTrait match {
      case MyCaseClass => JsObject("value" -> JsString("TEST"))
    }
  }
}

Now my test is failing by throwing DeserializationException:

"The my JSON format" when {
  "deserializing a JSON" must {
    "return correct object" in {
      val json = """{"value": "TEST"}""".asJson
      json.convertTo[MyTrait] must equal (MyCaseClass)
    }
  }
}

Obviously json.asJsObject.getFields("value")can not be matched to Seq(JsString("TEST")). Maybe this is related to using traits? But I have found example on official spray-json site https://github.com/spray/spray-json#providing-jsonformats-for-other-types

Any ideas how to properly match on field in JsObject?

Thanks! Best

1
I don't understand: Your test tests serialization, but you implemented deserialization (= read method)?Christian
Sorry wrong part of the code... you are right... fixed!zmeda

1 Answers

0
votes

Write variable name instead of string:

  override def read(json: JsValue): MyCaseClass = json.asJsObject.getFields("value") match {
    case Seq(JsString(value)) ⇒ MyCaseClass
    case _ ⇒ throw new DeserializationException(s"$json is not a valid case class")
  }

Does that work for you?

Update: Yes, your test is wrong. I tried it with the following (note parseJson instead of asJson) and it worked:

scala> val json = """{"value": "TEST"}""".parseJson
json: spray.json.JsValue = {"value":"TEST"}

scala> json.convertTo[MyCaseClass]
res2: MyCaseClass = MyCaseClass()

Update 2: Tried it with trait:

scala> import spray.json._
import spray.json._

scala> import spray.json.DefaultJsonProtocol._
import spray.json.DefaultJsonProtocol._

[Your code]

scala> val json = """{"value": "TEST"}""".parseJson
json: spray.json.JsValue = {"value":"TEST"}

scala> json.convertTo[MyTrait]
res1: MyTrait = MyCaseClass