创建案例类的写入和格式

时间:2014-02-11 22:49:22

标签: json scala playframework

对于本案例类:

case class People(names: Set[Int])

Travis Brown解释了如何在此answer创建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]Reads得到/定义的地方Writes写一下:

val peopleFormat: Format[People] = ...

1 个答案:

答案 0 :(得分:2)

好问题!您无法使用map的原因是因为Writes不是仿函数。

您可以将Writes[A]视为某种类似A => JsValue的内容。但是假设我有A => JsValueA => B。试着想出一些组合这些函数的方法来获得B => JsValue - 这是不可能的。

另一方面,

Reads[A]有点像JsValue => A,并且是一个仿函数 - 它有一个map方法,它采用A => B,用它组成Reads[A] / JsValue => A,并返回Reads[B] / JsValue => B

然而,

Writes是一个逆变仿函数,幸运的是Play knows that。当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]