这不编译:
package model
import play.api.libs.json._
case class Dog(id: Long, name: String, kind: String) {
def asJson() = Json.toJson(this)
}
object Dog {
implicit val writes = Json.writes[Dog]
}
错误:
53. Waiting for source changes... (press enter to interrupt)
[info] Compiling 1 Scala source to /Users/pablo/projects/mvp/target/scala-2.10/classes...
[error] /Users/pablo/projects/mvp/app/models/model2.scala:7: No Json deserializer found for type model.Dog. Try to implement an implicit Writes or Format for this type.
[error] def asJson() = Json.toJson(this)
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
更改随播对象(请注意显式类型):
object Dog {
implicit val writes: Writes[Dog] = Json.writes[Dog]
}
修复了这个问题。那是为什么?
答案 0 :(得分:1)
这不是一个真正的答案(但我需要很多空间来粘贴我的代码!)但这对我有用:
package model
import play.api.libs.json._
object Dog {
implicit val writes = Json.writes[Dog]
}
case class Dog(id: Long, name: String, kind: String) {
def asJson() = Json.toJson(this)
}
基本上我只是在课前移动了对象声明。这可能是因为Json.writes
使用宏,因此必须在使用构造的Write
实例之前进行。
答案 1 :(得分:1)
宏是一个实验性功能,所以我不会过分依赖它。我知道这更冗长,但如果你使用组合器它应该工作:
implicit val writes: Writes[Dog] = (
(JsPath \ "id").write[Long] and
(JsPath \ "name").write[String] and
(JsPath \ "kind").write[String]
)(unlift(Dog.unapply))
http://www.playframework.com/documentation/2.3.x/ScalaJsonCombinators
答案 2 :(得分:1)
Json.toJson
是一个宏,在编译时执行。在那个阶段,尚未进行类型分析,这意味着无法自动推断方法参数(this
)的类型(或者如果宏实现了执行此操作所需的额外功能,则可能会推断出它,但我认为这很难)。这就是你需要提供类型参数的原因,例如Json.toJson [Dog]。
声明伴侣对象时:
object Dog {
implicit val writes: Writes[Dog] = Json.writes[Dog]
}
您为该类型声明了一个隐式编写器。给定Scala的隐式解析规则,当您尝试将case类实例转换为JSON时,将在作用域中找到writer。所以它可以工作,但不是因为类中的asJson()
方法,而是因为隐式解析已经找到了在伴随对象中定义的编写器。