如何在 Play Framework 2.x 中实现嵌入式对象的隐式 Json 写入 [英] How to implement implicit Json Writes of embedded object in Play Framework 2.x

查看:18
本文介绍了如何在 Play Framework 2.x 中实现嵌入式对象的隐式 Json 写入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

there are two classes Foo and Bar. Foo contains a field of Bar. The question is, how do I implement an implicit json Writes for class 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
      )
    }
  }
}

当我尝试编译时,出现以下错误:

When I try to compile, I get the following error:

未找到类型 models.Bar 的 Json 反序列化器.尝试实施一个此类型的隐式写入或格式.

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

我不明白这个编译器错误,因为我为models.Bar 类实现了一个隐式的Writes.这里有什么问题?

I don't understand this compiler error, since I implemented an implicit Writes for models.Bar class. What is the problem here?

推荐答案

这是一个可见性问题,在声明隐式 Writes[Foo] 时,您并没有使隐式 Writes[Bar] 可见:

It's a question of visibility, when declaring the implicit Writes[Foo] you are not making visible the implicit Writes[Bar] to it:

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

Also, if you're using Play 2.1+ make sure to check out the brand new use of 2.10's macros: http://www.playframework.com/documentation/2.1.0/ScalaJsonInception

如果您对在 json 输出中用作键的 case 类和 val/vars 名称感到满意,就像您的情况顺便说一句,那么您可以使用两个单行:

If you're happy with the use of the case classes and the val/vars' names being used as keys in the json output, as in your case BTW, then you can use the two one-liners:

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

这将为您提供完全等效的内容:

That will give you the exact equivalent:

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

这篇关于如何在 Play Framework 2.x 中实现嵌入式对象的隐式 Json 写入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆