json - 如何在 Play Framework 2.x 中实现嵌入式对象的隐式 Json 写入

标签 json scala playframework playframework-2.0

FooBar 两个类。 Foo 包含 Bar 字段。问题是,如何为类 Foo 实现隐式 json Writes

代码如下:

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

当我尝试编译时,我收到以下错误:

No Json deserializer found for type models.Bar. Try to implement an implicit Writes or Format for this type.

我不理解这个编译器错误,因为我为 models.Bar 类实现了隐式写入。这里有什么问题?

最佳答案

这是一个可见性的问题,在声明隐式 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 输出中的键,就像您的案例 BTW 一样,那么您可以使用两个单行:

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

关于json - 如何在 Play Framework 2.x 中实现嵌入式对象的隐式 Json 写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15704756/

相关文章:

javascript - 我正在尝试从 ejs 模板中的 json 文件读取

scala - 继承 : override in class constructor

scala - 根据 ScalaQuery/SLICK 中列的 MAX 值选择行

java - 如何在Scala/Java中过滤中文标点符号?

hibernate - Play Framework 1 使用什么来实现 ORM?

json - 如何在 Go 中解码 JSON,它将多个元素作为类型数组返回,将单个元素作为类型返回

json - 如果您有 Reads[T] 和 Writes [T],那么 Format[T] 的目的是什么?

javascript - 如何在 Javascript 中访问这些数据?

mysql - 如何在Akka Actor中使用MYSQL jdbc实现

api - 为什么 Play 2.0.2 中有 Form 的 fold 方法?