Etam Etam - 2 months ago 13
Scala Question

Generic JSON Support

How do you use RootJsonFormat with Generics?

Do I have to copy paste every possibility like this:

trait IDJsonSupport
extends SprayJsonSupport
with DefaultJsonProtocol{

implicit object AddressIDFormat extends RootJsonFormat[ID[Address]] {
override def write(obj: ID[Address]): JsValue = JsNumber(obj.value)
override def read(json: JsValue): ID[Address] = json match {
case JsNumber(id) => new ID[Address](id.toLongExact)
case _ => deserializationError("Address ID expected")
}
}

implicit object CompanyIDFormat extends RootJsonFormat[ID[Company]] {
override def write(obj: ID[Company]): JsValue = JsNumber(obj.value)
override def read(json: JsValue): ID[Company] = json match {
case JsNumber(id) => new ID[Company](id.toLongExact)
case _ => deserializationError("Company ID expected")
}
}

implicit object NoteIDFormat extends RootJsonFormat[ID[Note]] {
override def write(obj: ID[Note]): JsValue = JsNumber(obj.value)
override def read(json: JsValue): ID[Note] = json match {
case JsNumber(id) => new ID[Note](id.toLongExact)
case _ => deserializationError("Note ID expected")
}
}

...


?

This:

implicit object AnyIDFormat extends RootJsonFormat[ID[_]] { ... }


does not work.

Answer

First, I assume ID class is defined like this:

case class ID[T](value: Long)

If so, you can define a generic format implicit def and specific formats will be automatically created by Scala compiler.

implicit def genericIDFormat[T]: RootJsonFormat[ID[T]] = new RootJsonFormat[ID[T]] {
  override def write(obj: ID[T]): JsValue = JsNumber(obj.value)
  override def read(json: JsValue): ID[T] = json match {
    case JsNumber(id) => ID(id.toLongExact)
    case _ => deserializationError("ID expected")
  }
}
Comments