Search code examples
scalagenericsakkaakka-httpspray-json

What is the correct way to register generic type to spray-json-support in akka-http Scala?


So, I have this class:

case class Something[T](data: Option[T] = None)

And i register it like the instruction said in https://github.com/spray/spray-json and in https://doc.akka.io/docs/akka-http/current/common/json-support.html. Like this:

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json.DefaultJsonProtocol

trait InternalJsonFormat extends SprayJsonSupport with DefaultJsonProtocol {
    import spray.json._

    implicit def somethingFormat[A :JsonFormat] = jsonFormat1(Something.apply[A])
}

And last i used complete from akka http directive. Like this:

import akka.http.scaladsl.server.Directives._

object ResponseIt extends InternalJsonFormat {
    def apply[T](rawData: T) = {
        val theResponse = Something(data = Some(rawData))
        complete(theResponse)
    }
}

And then i get an error in complete(theResponse). It said

Type mismatch, expected: ToResponseMarshallable, actual: Something[T]

===========================================================

I have try to edit the last code for debugging purpose, like this:

object ResponseIt extends InternalJsonFormat {
    import spray.json._

    def apply[T](rawData: T) = {
        val theResponse = Something(data = Some(rawData))
        val trying = theResponse.toJson
        complete(theResponse)
    }
}

and get new error in val trying = theResponse.toJson. like this:

No implicits found for parameter writer: JsonWriter[Something[T]] 

So, i really confused what is wrong in my code?. Is there any correct way to use the spray json support in akka http?

Thanks in advance


Solution

  • You see, there is no evidence for existence of JsonFormat for your T here:

     def apply[T](rawData: T) = {
            // ^--- here
            val theResponse = Something(data = Some(rawData))
            val trying = theResponse.toJson
            complete(theResponse)
        }
    

    One can rewrite this method to provide JsonFormat for generic T:

    def apply[T](rawData: T)(implicit formatter: JsonFormat[T])