这将编译。 (请注意,implicit val subscriptionReads由外部隐式声明为emailIdReadsintervalReads组成,而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))

}

我想念什么?为什么我不能用平等代替平等?此外,为什么我可以使用Reads而不是Writes来做到这一点。我想了解为什么这不起作用。
and的相关定义在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 Not Writes类型定义的。从.write [String]中得到的实际上是OWrites [String]类型。它不起作用的原因是,您正在显式指定更宽的类型Writes。

10-04 10:58