Search code examples
scalainheritancesprayspray-json

spray-json serializing inheritance case class


I have following class structure which involves inheritance

sealed trait GeometryObject
case class Point(coordinates: Array[Double],`type` :GeometryObjectsType) extends GeometryObject

case class Polygon(coordinates: Array[Array[Array[Double]]],`type` :GeometryObjectsType) extends GeometryObject

My protocol looks as follows:

object GeoJsonProtocol extends DefaultJsonProtocol {
  implicit val geometryObjectsTypeFormat = GeometryObjectsTypeFormat
  implicit val polygonFormat = jsonFormat2(Polygon)
  implicit val pointFormat = jsonFormat2(Point)
}

Getting an error - could not find implicit value for evidence parameter of type GeometryObject.

Is there a way how to deal with that and keep inheritance flexibility?


Solution

  • There is a need for class hierarchy parent format as follows:

    object GeometryObjectLeafFormats extends DefaultJsonProtocol{
      implicit val geometryObjectsTypeFormat = GeometryObjectsTypeFormat
      implicit val polygonFormat = jsonFormat2(Polygon)
      implicit val pointFormat = jsonFormat2(Point)
    }
    
    object GeometryObjectFormat extends JsonFormat[GeometryObject] {
      import GeometryObjectLeafFormats._
      override def read(json: JsValue): GeometryObject = json match {
        case known:JsObject if known.fields.contains("type") =>
          known.fields.get("type").get match{
            case JsString(PointType.value) => pointFormat.read(known)
            case JsString(PolygonType.value) => polygonFormat.read(known)
            case unknown => deserializationError(s"unknown GeometryObject: ${unknown}")
          }
        case unknown => deserializationError(s"unknown GeometryObject: ${unknown}")
      }
    
      override def write(obj: GeometryObject): JsValue = obj match {
        case x:Point => pointFormat.write(x)
        case x:Polygon=> polygonFormat.write(x)
        case unrecognized => serializationError(s"Serialization problem ${unrecognized}")
      }
    }
    

    Note: I have separate class hierarchy denoting the type which is serialized to type field which is mandatory in order to make class hierarchy serialization working.