Play の (2.2) Scala JSON コンビネーターを使用して Case クラスに見つからない任意の値を書き込む
-
21-12-2019 - |
質問
を実装したいのですが、 Writes
シリアル化されているクラスで見つからない JSON オブジェクトを出力します。
ケースクラスの場合:
case class Foo(i:Int, s:String)
私は生産しようとしています:
{
"i": <int>,
"s": "<string>",
"other": "Some value."
}
素朴な最初の試みは次のとおりです。
val writes: Writes[Foo] = ((
(__ \ "i").write[Int] and
(__ \ "s").write[String] and
(__ \ "other").write("Some value.")
)(unlift(Foo.unapply))
当然のことながら、これは後続のものとしてコンパイルされません。 and
呼び出しは CanBuild3
そして Foo
さんの unapply
を生成します Tuple2
. 。結果に値を追加して、 Tuple3
, 、しかし私が見つけたこと かなり悪そうに見える そしてその 言語管理者はそれを実装しないでしょう.
これを回避する方法はありますが、結果として得られる JSON に追加するデコレータ値でモデル クラスを汚染したくありません。
助言がありますか?
あなたに注目する価値があります できる 別の方向に進み、次の値を提供します Reads.pure
値が JSON に存在しないが、結果として得られるオブジェクトによって指定される場合。
解決
少し脱糖することで、これを非常に簡単に行うことができます。
val writes: Writes[Foo] = (
(__ \ "i").write[Int] and
(__ \ "s").write[String] and
(__ \ "other").write[String]
)(foo => (foo.i, foo.s, "Some value."))
の unlift(Foo.unapply)
から関数を取得するための単なる派手な方法です Foo
前述の適用ビルダー式で必要な種類のタプルに変換し、必要なものを追加できる独自の関数に置き換えることができます。
もし、あんたが 本当に さらにきれいな構文が必要な場合は、次を使用できます 形のない:
import shapeless.syntax.std.tuple._
val writes: Writes[Foo] = (
(__ \ "i").write[Int] and
(__ \ "s").write[String] and
(__ \ "other").write[String]
)(_ :+ "Some value.")
美しいですが、やりすぎかもしれません。
他のヒント
別のオプションは、追加値を返すunapply
を実装するオブジェクトビルダーを使用することです。これにより、書き込みがクリーナーになりますが、新しいオブジェクトを追加します。適用方法と未申成方法の両方が最終的なオブジェクトへの追加マッサージに使用できるため、これを有用しました(例: HTTPS://stackoverflow.com/a/22504468/1085606
case class Foo(i: Int, s: String)
object FooBuilder {
def unapply(foo: Foo): Option[(Int, String, String)] = {
Some((foo.i, foo.s, "Some extra value"))
}
}
val writes: Writes[Foo] = ((
(__ \ "i").write[Int] and
(__ \ "s").write[String] and
(__ \ "other").write[String]
)(unlift(FooBuilder.unapply))
.