24

との 2 つのクラスがFooありBarます。Fooのフィールドが含まれていますBarWrites問題は、 classの暗黙的な 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 デシリアライザーが見つかりません。この型の暗黙の Writes または Format を実装してみてください。

暗黙の Writes for models.Bar クラスを実装したため、このコンパイラ エラーがわかりません。ここで何が問題なのですか?

4

1 に答える 1

33

これは可視性の問題です。暗黙の 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

ケース クラスの使用と val/vars の名前が json 出力のキーとして使用されることに満足している場合は、あなたの場合のように、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
  }
}
于 2013-03-29T14:45:32.560 に答える