Reputation:
I'm using play-json to map Json to case classes or enums. I'm looking for a smart way of creating Formats
implicitly, since my project contains many types definitions.
At the moment I created a simple function to generate Formats
for Enums:
def formatEnum[E <: Enumeration](enum: E) = Format(Reads.enumNameReads(enum), Writes.enumNameWrites)
But it takes a non-implicit argument so it cannot be used as implicit converter.
I tried to do the same for case classes:
implicit def caseFormat[A] = Json.format[A]
But I get the error "No unapply or unapplySeq function found", since Json.format
is a macro which inspect the structure of the class.
Then I tried to create my macro in this way:
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
implicit def caseFormat[A](): Format[A] = macro impl[A]
def impl[A: c.WeakTypeTag](c: Context)(): c.Expr[Reads[A]] = {
import c.universe._
val TypeRef(pre, sym, args) = weakTypeTag[A].tpe
val t = args.head
val expr = q"Json.format[$t]"
c.Expr[Reads[A]](expr)
}
But the compiler does not find the implicit Format
, though there is an implicit def that should generate the value.
Of course I can simply define many implicit val, but I think there is a smarter way to do it.
Upvotes: 0
Views: 617
Reputation: 449
Assuming you have lots of case classes and you wish to json serialize it on the fly without having to write a play-json writer.
import play.api.libs.json._
import scala.reflect.runtime.{universe => ru}
implicit class writeutil[T: ru.TypeTag](i: T) {
implicit val writer = Json.writes[T]
def toJson() = Json.toJson(i)
}
def toInstance[T: ru.TypeTag](s: String): Option[T] = {
implicit val reader = Json.reads[T]
Json.fromJson[T](Json.parse(s)) match {
case JsSuccess(r: T, path: JsPath) => Option(r)
case e: JsError => None
}
}
An optimal implementation would be to re-use the reader/writer by caching and lookup. You can also read more about play-json.
You can use this as:
case class Entity(a: String, b: Int)
val e = Entity("Stack", 0)
e.toJson()
Upvotes: 0