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

Generate case classes serializer and deserializer implicitly using play-json

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


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

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

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


我尝试对案例 classes:

做同样的事情
implicit def caseFormat[A] = Json.format[A]

但是我收到错误 "No unapply or unapplySeq function found",因为 Json.format 是一个检查 class.

结构的宏

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

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,但我认为有更聪明的方法来做到这一点。

假设您有很多案例 类 并且您希望 json 即时将其序列化而无需编写剧本-json 编写器。

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

最佳实施方式是通过缓存和查找重新使用 reader/writer。您还可以阅读有关 play-json.

的更多信息

您可以将其用作:

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

e.toJson()