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]

Json.formatしかし、クラスの構造を検査するマクロであるため、「unapply または unapplySeq 関数が見つかりません」というエラーが表示されます。

次に、この方法でマクロを作成しようとしました:

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ただし、値を生成する必要がある暗黙の定義がありますが、コンパイラは暗黙の を検出しません。


もちろん、多くの暗黙の val を単純に定義することもできますが、もっとスマートな方法があると思います。

4

1 に答える 1

0

多くのケース クラスがあり、play-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
    }
}

最適な実装は、キャッシュとルックアップによってリーダー/ライターを再利用することです。play-jsonについても詳しく読むことができます。

これを次のように使用できます。

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

e.toJson()
于 2016-11-26T20:56:50.313 に答える