/ / Cómo implementar escrituras Json implícitas de objetos incrustados en Play Framework 2.x - json, scala, playframework, playframework-2.0

Cómo implementar escrituras Json implícitas de objetos incrustados en Play Framework 2.x - json, scala, playframework, playframework-2.0

hay dos clases Foo y Bar. Foo contiene un campo de Bar. La pregunta es, ¿cómo implemento un json implícito? Writes para 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 un Escrituras implícitas o Formato para este tipo.

No entiendo este error del compilador, ya que implementé una clase implícita de Escrituras para modelos. Barra. ¿Cuál es el problema aquí?

Respuestas

29 para la respuesta № 1

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