【问题标题】:Playframeworks json Writes implicit requires explicit type, why?Playframeworks json 写入隐式需要显式类型,为什么?
【发布时间】:2014-05-14 14:45:55
【问题描述】:

这不能编译:

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

解决了这个问题。这是为什么呢?

【问题讨论】:

  • 请注意,Json.writes 签名是 def writes[A]: Writes[A],因此类型正是显式类型。
  • 我对 scala 的了解不够,无法回答这个问题,但 Writes[-A] 是逆变的可能很重要。我不知道 Scala 在这种情况下是否可以处理隐式。

标签: json scala playframework playframework-2.2 implicit-conversion


【解决方案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 实例之前发生。

【讨论】:

  • 赞成,感谢您的信息。我真的希望有一个不同于声明顺序的解释。
【解决方案2】:

Json.toJson是一个宏,在编译时执行。在那个阶段,尚未进行类型分析,这意味着无法自动推断方法参数 (this) 的类型(或者如果宏实现了这样做所需的额外功能,则可能可以推断出来,但是我想这很困难)。这就是为什么您需要提供类型参数,例如 Json.toJson[Dog]。

当你像这样声明一个伴生对象时:

object Dog {
  implicit val writes: Writes[Dog] = Json.writes[Dog]
}

您为该类型声明了一个隐式编写器。鉴于 Scala 的隐式解析规则,当您尝试将案例类实例转换为 JSON 时,将在范围内找到编写器。所以它可以工作,但不是因为你的类中的asJson() 方法,而是因为隐式解析找到了伴随对象中定义的编写器。

【讨论】:

    【解决方案3】:

    宏是一项实验性功能,因此我不会过分依赖它。我知道这要冗长得多,但是如果您使用组合器,它应该可以工作:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 2013-09-25
      • 2015-09-30
      • 1970-01-01
      相关资源
      最近更新 更多