Foo
とBar
の2つのクラスがあります。 Foo
にはBar
のフィールドが含まれます。問題は、クラスWrites
に暗黙のjson Foo
を実装するにはどうすればよいですか?
これがコードです:
package models
import play.api.libs.json._
case class Foo(id: String, bar: Bar)
object Foo {
implicit val implicitFooWrites = new Writes[Foo] {
def writes(foo: Foo): JsValue = {
Json.obj(
"id" -> foo.id,
"bar" -> foo.bar
)
}
}
}
case class Bar(x: String, y: Int)
object Bar {
implicit val implicitBarWrites = new Writes[Bar] {
def writes(bar: Bar): JsValue = {
Json.obj(
"x" -> bar.x,
"y" -> bar.y
)
}
}
}
コンパイルしようとすると、次のエラーが発生します。
タイプmodels.BarのJsonデシリアライザが見つかりません。このタイプの暗黙的な書き込みまたはフォーマットを実装してみてください。
Models.Barクラスに暗黙のWritesを実装したため、このコンパイラエラーを理解できません。ここの問題は何ですか?
これは、暗黙的なWrites [Foo]を宣言するときに、暗黙的なWrites [Bar]を可視化しないという可視性の問題です。
scala> :paste
// Entering paste mode (ctrl-D to finish)
import play.api.libs.json._
case class Bar(x: String, y: Int)
object Bar {
implicit val implicitBarWrites = new Writes[Bar] {
def writes(bar: Bar): JsValue = {
Json.obj(
"x" -> bar.x,
"y" -> bar.y
)
}
}
}
case class Foo(id: String, bar: Bar)
object Foo {
import Bar._
implicit val implicitFooWrites = new Writes[Foo] {
def writes(foo: Foo): JsValue = {
Json.obj(
"id" -> foo.id,
"bar" -> foo.bar
)
}
}
}
// Exiting paste mode, now interpreting.
import play.api.libs.json._
defined class Bar
defined module Bar
defined class Foo
defined module Foo
scala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1))))
res0: String =
{
"id" : "23",
"bar" : {
"x" : "x",
"y" : 1
}
}
また、Play 2.1以降を使用している場合は、2.10のマクロの新しい使用方法を確認してください。 http://www.playframework.com/documentation/2.1.0/ScalaJsonInception
ケースBTWのように、json出力でキーとして使用されているケースクラスとval/varsの名前の使用に満足している場合は、2つのワンライナーを使用できます。
implicit val barFormat = Json.writes[Bar]
implicit val fooFormat = Json.writes[Foo]
それはあなたに正確に同等のものを与えます:
scala> import play.api.libs.json._
import play.api.libs.json._
scala> case class Bar(x: String, y: Int)
defined class Bar
scala> case class Foo(id: String, bar: Bar)
defined class Foo
scala> implicit val barWrites = Json.writes[Bar]
barWrites: play.api.libs.json.OWrites[Bar] = play.api.libs.json.OWrites$$anon$2@257cae95
scala> implicit val fooWrites = Json.writes[Foo]
fooWrites: play.api.libs.json.OWrites[Foo] = play.api.libs.json.OWrites$$anon$2@48f97e2a
scala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1))))
res0: String =
{
"id" : "23",
"bar" : {
"x" : "x",
"y" : 1
}
}