Search code examples
scalasprayspray-json

custom spray-json marshaller for a case class with Value type


case class HydraQueueMessage(tableType: HydraTableName.Value, payload: String)


object MedusaElementFormat extends DefaultJsonProtocol {
  implicit object HydraElementFormat extends RootJsonFormat[HydraQueueMessage] {
    def write(message: HydraQueueMessage) = JsObject(
      MedusaEnum.HydraTableName.toString -> JsString(message.tableType.toString),
      "payload" ->  JsString(message.payload)
    )
    def read(value: JsValue) = {
      value.asJsObject.getFields("tableType", "payload") match {
        case Seq(JsString(tableType), JsString(payload)) =>
          new HydraQueueMessage(tableType = tableType, payload = payload)
      }
    }
  }
}

There's a type miss-match in this example, is there a cleaner way to achieve this? And still having the tableType as a Value and not String?

My marshaller throws a type miss-match with the Value type, I can't marshall JsValue either. So how would I proceed to marshall the HydraQueueMessage case class without using a String type for tableType?


Solution

  • You are trying to process too much at once. I would divide your problem in 2:

    1. Process HydraTableName.Value
    2. Process HydraQueueMessage

    That will make things much easier.

    To process your enum:

    implicit object StepFormatJsonFormat extends RootJsonFormat[HydraTableName.Value] {
      def write(obj: HydraTableName.Value): JsValue = JsString(obj.toString)
    
      def read(jsonValue: JsValue): HydraTableName.Value = jsonValue match {
        case JsString(stringObj) => HydraTableName.withName(stringObj)
        case otherValue => throw new DeserializationException(s"HydraTableName.Value not found in ${otherValue.toString}")
      }
    }
    

    Then the typical case class formatting:

    implicit val HydraQueueMessageFormat = jsonFormat2(HydraQueueMessage.apply)
    

    Probably the way to process the enum should be adapted. If you include the HydraTableName, I can update the code.