json scala playframework playframework-2.0

Cómo implementar escrituras Json implícitas de objetos incrustados en Play Framework 2.x



scala playframework (1)

Hay dos clases de Foo y Bar . Foo contiene un campo de Bar . La pregunta es, ¿cómo implemento un json Writes implícito para la clase Foo ?

Aquí está el código:

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 ) } } }

Cuando intento compilar, me sale el siguiente error:

No se ha encontrado ningún deserializador Json para modelos de tipo. Barra. Trate de implementar una escritura implícita o un formato para este tipo.

No entiendo este error del compilador, ya que implementé una escritura implícita para la clase models.Bar. ¿Cuál es el problema aquí?


Es una cuestión de visibilidad, al declarar las Escrituras implícitas [Foo] no está haciendo visibles las Escrituras [Barras] implícitas:

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 } }

Además, si está utilizando Play 2.1+, asegúrese de verificar el nuevo uso de las macros de 2.10: http://www.playframework.com/documentation/2.1.0/ScalaJsonInception

Si está satisfecho con el uso de las clases de casos y los nombres de val / vars que se utilizan como claves en la salida json, como en su caso BTW, entonces puede usar las dos líneas de una línea:

implicit val barFormat = Json.writes[Bar] implicit val fooFormat = Json.writes[Foo]

Eso te dará el equivalente exacto:

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 } }