创建案例类的写入和格式 [英] Create Writes and Format of Case Class
问题描述
对于这个案例类:
case class People(names: Set[Int])
Travis Brown 在此解释了如何创建 PeopleReads: Reads[People]
答案:
Travis Brown explained how to create PeopleReads: Reads[People]
at this answer:
implicit val PeopleReads =
(__ "names").read[Set[Id]].map(People)
但是,我正在尝试实现 PeopleWrites: Writes[People]
:
But, I'm trying to implement 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)))
我该如何解决这个错误?
How can I resolve this error?
另外,我如何编写 Format[People]
来获取/定义 Reads
和 Writes
:
Also, how can I write Format[People]
where I get/define both Reads
and Writes
:
val peopleFormat: Format[People] = ...
?
推荐答案
好问题!不能使用 map
的原因是 Writes
不是函子.
Good question! The reason you can't use map
is because Writes
isn't a functor.
您可以将 Writes[A]
视为类似于 A =>JsValue
.但是假设我有一个 A =>JsValue
和一个 A =>B
.尝试想出一些方法来组合这些函数以获得 B =>;JsValue
——这是不可能的.
You can think of Writes[A]
as something kind of like A => JsValue
. But suppose I've got a A => JsValue
and a A => B
. Try to come up with some way of composing those functions to get a B => JsValue
—it's just not possible.
Reads[A]
有点像 JsValue =>A
,并且是一个函子——它有一个 map
方法,它接受一个 A =>B
,用 Reads[A]
/JsValue => 组合起来A
,并返回一个 Reads[B]
/JsValue =>B
.
Reads[A]
, on the other hand, is kind of like JsValue => A
, and is a functor—it has a map
method that takes a A => B
, composes it with the Reads[A]
/ JsValue => A
, and returns a Reads[B]
/ JsValue => B
.
Writes
是一个逆变函子,幸运的是 Play 知道这一点.当 F
是逆变函子时,F[A]
有一个方法 contramap[B](f: B => A)
而不是通常的map[B](f: A => B)
.所以你可以这样写:
Writes
is, however, a contravariant functor, and luckily enough Play knows that. When F
is a contravariant functor, F[A]
has a method contramap[B](f: B => A)
instead of the usual map[B](f: A => B)
. So you can just write this:
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 =>设置[Int]
.将它们与 contramap
结合起来给我们一个 Writes[People]
.
Here (__ 'names).write[Set[Int]]
is a Writes[Set[Int]]
and (_.names)
is a function People => Set[Int]
. Combining them with contramap
gives us a Writes[People]
.
这篇关于创建案例类的写入和格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!