json - 为什么 Scala 编译器会区别对待这两个代码块?

标签 json scala playframework

这会编译。 (请注意,implicit val subscriptionReadsemailIdReadsintervalReads 声明在隐式之外,而 subscriptionWrites 由隐式内部声明的Writes组成。)

import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Subscription(emailId: String, interval: String)

object Subscription {

  val emailIdReads: Reads[String]  = (JsPath \ "emailId").read[String]

  val intervalReads: Reads[String] = (JsPath \ "interval").read[String]

  implicit val subscriptionReads: Reads[Subscription] = (
      emailIdReads and
      intervalReads
    )(Subscription.apply _)

  implicit val subscriptionWrites: Writes[Subscription] = (
    (JsPath \ "emailId").write[String] and
    (JsPath \ "interval").write[String]
    )(unlift(Subscription.unapply))
}

然而下面的代码——其中两个 Writes 值被声明在隐式之外——没有编译,产生错误消息:“值 and 不是 play.api.libs.json.Writes[String] 的成员。”

import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Subscription(emailId: String, interval: String)

object Subscription {

  val emailIdReads: Reads[String]  = (JsPath \ "emailId").read[String]

  val intervalReads: Reads[String] = (JsPath \ "interval").read[String]

  implicit val subscriptionReads: Reads[Subscription] = (
      emailIdReads and
      intervalReads
    )(Subscription.apply _)

  val emailIdWrites: Writes[String]  = (JsPath \ "emailId").write[String]

  val intervalWrites: Writes[String] = (JsPath \ "interval").write[String]

  implicit val subscriptionWrites: Writes[Subscription] = (
      emailIdWrites and
      intervalWrites
    )(unlift(Subscription.unapply))

}

我错过了什么?为什么我不能用 equals 代替 equals?此外,为什么我可以使用Reads 而不是Writes。我想理解为什么这行不通。

的相关定义见play.api.libs.functional

package play.api.libs.functional

import scala.language.higherKinds

case class ~[A, B](_1: A, _2: B)

trait FunctionalCanBuild[M[_]] {

  def apply[A, B](ma: M[A], mb: M[B]): M[A ~ B]

}

class FunctionalBuilderOps[M[_], A](ma: M[A])(implicit fcb: FunctionalCanBuild[M]) {

  def ~[B](mb: M[B]): FunctionalBuilder[M]#CanBuild2[A, B] = {
    val b = new FunctionalBuilder(fcb)
    new b.CanBuild2[A, B](ma, mb)
  }

  def and[B](mb: M[B]): FunctionalBuilder[M]#CanBuild2[A, B] = this.~(mb)
}

/* Additional arities elided */

最佳答案

我不得不深入挖掘一下,原因实际上是在这个文件中,其中定义了所需的隐式:

https://github.com/playframework/playframework/blob/26a9c7625d6c482abf1c6ecedacff34d670bee01/framework/src/play-json/src/main/scala/play/api/libs/json/Writes.scala

它是为类型 OWrites 而不是 Writes 定义的。你从 .write[String] 得到的实际上是 OWrites[String] 类型。它不起作用的原因是,您明确指定了更宽的 Writes 类型。

关于json - 为什么 Scala 编译器会区别对待这两个代码块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35352966/

相关文章:

ios - arrayWithContentsOfFile 和 arrayWithContentsOfURL 无

python - 更改 json 值并创建新值

JSON 提供者 jackson 使用 boolean 类型序列化和反序列化的问题

Scala - 减少功能

Scala - 抽象类型和隐式参数解析

java - 无法使用注入(inject)器注入(inject) Play 的 WSClient 实例

json - Lua - 如何传递一个API调用获得的字符串来调用另一个API调用

json - 根据类型 Play Scala 读/写

java - 安装 play 框架 mongodb morphia 模块

java - 在同一 Play Framework 项目中同时使用 Ebean 和 JPA