创建案例类的写作和格式 [英] Create Writes and Format of Case Class
问题描述
对于此案例类:
case class People(names: Set[Int])
特拉维斯·布朗解释了如何在此
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)))
,出现以下编译时错误:
with the following compile-time error:
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]
和Writes
都定义/定义的地方写Format[People]
:
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
,并且是一个函子-它具有采用A => B
的map
方法,并由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
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 => Set[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屋!