如何在 Play Framework 2.x 中实现嵌入对象的隐式 Json 写入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15704756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement implicit Json Writes of embedded object in Play Framework 2.x
提问by schub
there are two classes Fooand Bar. Foocontains a field of Bar. The question is, how do I implement an implicit json Writesfor class Foo?
有两个类Foo和Bar。Foo包含一个字段Bar。问题是,如何Writes为 class实现隐式 json Foo?
Here is the code:
这是代码:
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:
当我尝试编译时,出现以下错误:
No Json deserializer found for type models.Bar. Try to implement an implicit Writes or Format for this type.
找不到类型 models.Bar 的 Json 反序列化器。尝试为这种类型实现隐式写入或格式。
I don't understand this compiler error, since I implemented an implicit Writes for models.Bar class. What is the problem here?
我不明白这个编译器错误,因为我为 models.Bar 类实现了一个隐式写入。这里有什么问题?
回答by jsirocchi
It's a question of visibility, when declaring the implicit Writes[Foo] you are not making visible the implicit Writes[Bar] to it:
这是一个可见性问题,在声明隐式 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
}
}
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
此外,如果您使用的是 Play 2.1+,请务必查看 2.10 宏的全新用法:http: //www.playframework.com/documentation/2.1.0/ScalaJsonInception
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:
如果您对 case 类的使用感到满意,并且 val/vars 的名称在 json 输出中用作键,就像您的情况 BTW,那么您可以使用两个单行:
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@257cae95
scala> implicit val fooWrites = Json.writes[Foo]
fooWrites: play.api.libs.json.OWrites[Foo] = play.api.libs.json.OWrites$$anon@48f97e2a
scala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1))))
res0: String =
{
"id" : "23",
"bar" : {
"x" : "x",
"y" : 1
}
}

