The spray-json library extends basic Scala types with a toJson
method. I'd like to convert an Any
into a JsValue
if there is such a pimp for the underlying type. My best attempt works, but is verbose:
import cc.spray._
val maybeJson1: PartialFunction[Any, JsValue] = {
case x: BigDecimal => x.toJson
case x: BigInt => x.toJson
case x: Boolean => x.toJson
case x: Byte => x.toJson
case x: Char => x.toJson
case x: Double => x.toJson
case x: Float => x.toJson
case x: Int => x.toJson
case x: Long => x.toJson
case x: Short => x.toJson
case x: String => x.toJson
case x: Symbol => x.toJson
case x: Unit => x.toJson
}
Ideally, I'd prefer something (impossible) like this:
def maybeJson2(any: Any): Option[JsValue] = {
if (pimpExistsFor(any))
Some(any.toJson)
else
None
}
Is there a way to do this without enumerating every type that has been enriched?
There is a way, but it requires a lot of reflection and therefore is quite a headache. The basic idea is as follows. The
DefaultJsonProtocol
object inherits a bunch of traits that contain implicit objects which containwrite
methods. Each of those will have an accessor function, but you won't know what it's called. Basically, you'll just take all methods that take no parameters and return one object that has awrite
method that takes the class of your object and returns aJsValue
. If you find exactly one such method that returns one such class, use reflection to call it. Otherwise, bail.It would look something like this (warning, untested):
Anyway, you're best off pulling the
DefaultJsonProtocol
class apart in the REPL step by step and finding out how to reliably identify the objects that define the writers, and then get thewrite
methods out of them.