一尘不染

创建案例类的写作和格式

json

对于此案例类:

case class People(names: Set[Int])

特拉维斯·布朗(Travis Brown)解释了如何创建PeopleReads:Reads[People]此答案:

implicit val PeopleReads = 
       (__ \ "names").read[Set[Id]].map(People)

但是,我正在尝试实现PeopleWrites: Writes[People]

 implicit val PeopleWrites: Writes[People] = 
    (JsPath \  "names").write[Set[Int]].map(unlift(x => Some((x.names)))

出现以下编译时错误:

scala> People( Set(1,2,3))
res5: People = People(Set(1, 2, 3))

scala>  implicit val PeopleWrites: Writes[People] = 
      (JsPath \  "names").write[Set[Int]].map(unlift(x => Some((x.names))))
<console>:21: error: value map is not a member of 
                play.api.libs.json.OWrites[Set[Int]]
              implicit val PeopleWrites: Writes[People] = 
                (JsPath \  "names").write[Set[Int]].
                                      map(unlift(x => Some((x.names)))

如何解决此错误?

另外,我怎么写我Format[People]在哪里得到/定义了ReadsWrites

val peopleFormat: Format[People] = ...


阅读 266

收藏
2020-07-27

共1个答案

一尘不染

好问题!您不能使用的原因map是因为Writes它不是函子。

您可以将其Writes[A]视为类似A => JsValue。但是,假设我有一个A => JsValue和一个A => B。尝试想出一些方法来构成这些函数以获得一个B => JsValue—这是不可能的。

Reads[A]另一方面,有点像JsValue => A,并且是一个函子-它具有一种map方法,该方法采用a A => B并将其与Reads[A]/ 组成JsValue => A并返回Reads[B]/ JsValue => B

Writes但是,它是一个 协变
函子,幸运的是Play知道这一点。当F是逆函子时,F[A]有一个方法contramap[B](f: B => A)代替了通常的方法map[B](f: A => B)。所以你可以这样写:

case class People(names: Set[Int])

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

implicit val PeopleWrites: Writes[People] =
  (__ \ 'names).write[Set[Int]].contramap(_.names)

(__ \ 'names).write[Set[Int]]是一个Writes[Set[Int]]并且(_.names)是一个函数People => Set[Int]。与他们结合在一起contramap给我们一个Writes[People]

2020-07-27