使用play-json隐式生成case类序列化器和反序列化器

时间:2016-11-26 09:51:52

标签: scala playframework scala-macros play-json

我使用play-json将Json映射到案例类或枚举。我正在寻找一种隐式创建Formats的智能方法,因为我的项目包含许多类型的定义。

目前我创建了一个简单的函数来为枚举生成Formats

def formatEnum[E <: Enumeration](enum: E) = Format(Reads.enumNameReads(enum), Writes.enumNameWrites)

但它需要一个非隐式参数,因此不能用作隐式转换器。

我尝试对案例类做同样的事情:

implicit def caseFormat[A] = Json.format[A]

但我收到错误&#34;找不到unapply或unapplySeq函数&#34;,因为Json.format是一个检查类结构的宏。

然后我尝试以这种方式创建我的宏:

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)
}

但是编译器找不到隐式Format,尽管有一个隐式def应该生成值。

当然我可以简单地定义许多隐式val,但我认为有一种更聪明的方法可以做到。

1 个答案:

答案 0 :(得分:0)

假设您有很多案例类,并且希望json能够即时序列化它而无需编写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
    }
}

最佳实现是通过缓存和查找重用读取器/写入器。您还可以阅读有关play-json

的更多信息

您可以将其用作:

case class Entity(a: String, b: Int)
val e = Entity("Stack", 0)

e.toJson()