0

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


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

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

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


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

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

但是我收到错误“没有找到 unapply 或 unapplySeq 函数”,因为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,但我认为有一个更聪明的方法来做到这一点。

4

1 回答 1

0

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

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

您可以将其用作:

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

e.toJson()
于 2016-11-26T20:56:50.313 回答