2016-11-26 1 views
0

私はJsonをケースクラスまたはenumにマップするためにplay-jsonを使用しています。私はFormatsを暗黙的に作成するスマートな方法を探しています。私のプロジェクトには多くの型定義が含まれているからです。play-jsonを使用して暗黙的にcaseクラスのシリアライザとデシリアライザを生成する


は、現時点では私は列挙型のためFormatsを生成するための簡単な関数を作成:

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

をしかし、それは暗黙のコンバータとして使用することはできませんので、それは非暗黙の引数を取ります。


私はケースクラスのために同じことを実行しようとしました:

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

しかしJson.formatは、クラスの構造を調べるマクロですので、私は、エラー「が見つかりません適用を解除するか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) 
} 

しかし、値を生成する必要があります暗黙のDEFがありますが、コンパイラは、暗黙のFormatを見つけることができません:

は、その後、私はこのように私のマクロを作成しようとしました。


私は単純に多くの暗黙のvalを定義することができますが、私はそれを行うよりスマートな方法があると思います。

+0

あなたは、としてこれを使用することができますか? – phantomastray

答えて

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() 
+0

あなたの答えに感謝します! – WalkerTR

+0

うれしいです。 :) – phantomastray

+0

動作しません。 'scala.ScalaReflectionException:型Tがクラスではない'を取得する – Vladislav

関連する問題