I have some code that streams a response by converting a Stream
of case classes to json representations using spray.json. This works fine for a single case class, but I want to genericize it.
So I'm starting with case classes like this:
import spray.json._
import spray.json.DefaultJsonProtocol._
case class Item(foo: String, bar: Int)
case class Report(baz: String, stream: Stream[Item])
object Protocol { implicit val ItemFormat = jsonFormat2(Item) }
In my report streaming method I have code like this (highly simplified):
def streamReport(...) {
import Protocol._
val handler: PartialFunction[Try[Any], String] = {
case Success(Report(_, stream)) =>
stream.head.toJson.compactPrint
}
}
What I'd like to do is genericize Report
to support more than Item:
case class Report[T](baz: String, stream: Stream[T])
But now, of course, the streamReport
method can't find a JsonWriter
in scope for type Any
.
I can do something close to what I want if I add a type parameter with context bound to streamReport
, and pass in the Report
directly:
def jsonStream[T : JsonWriter](report: Report[T]): String =
implicitly[JsonWriter[T]].write(report.stream.head).compactPrint
However, I cannot figure out how to get this to work with the PartialFunction
. The following does not compile (and wouldn't fit exactly anyway as the signature of the partial function is different than above):
def handler[T : JsonWriter](): PartialFunction[T, String] = {
case Success(Report(_, stream)) =>
implicitly[JsonWriter[T]].write(report.stream.head).compactPrint
}
I'm not sure where it's going wrong. Does it have to do with type erasure, or a problem with having Try[Any]
as the parameter type on my partial function? How can I get the implicit JsonWriter I need for the element type of the stream?
My guess is that Any
is not the problem, the problem is trying to match case Success(Report(_, stream))
, after the definition for Report
is now Report[T]
.
Also, in order to find the right implicit conversion, the compiler needs to understand the type involved (in compile time). Try using something like this:
def streamReport[T](...) {
import Protocol._
val handler: PartialFunction[Try[Any], String] = {
case Success(Report[T](_, stream)) =>
stream.head.toJson.compactPrint
}
}
That way, the compiler will know what is being matched, and can infer the right type.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.