2014-01-30 21 views
2

如何爲我的People案例類創建play.api.libs.Reads爲JSON集類型定義`Reads`

scala> type Id = Long 
defined type alias Id 

scala> case class People(names: Set[Id]) 
defined class People 

scala> implicit val PeopleReads: Reads[People] = (
    |  (__ \ "names").read[Set[Id]])(People) 
<console>:21: error: overloaded method value read with alternatives: 
    (t: Set[Id])play.api.libs.json.Reads[Set[Id]] <and> 
    (implicit r: play.api.libs.json.Reads[Set[Id]])play.api.libs.json.Reads[Set[Id]] 
cannot be applied to (People.type) 
      (__ \ "names").read[Set[Id]])(People) 

回答

3

(...)(People)語法設計,當你已經建立起來的論點(當然,在技術上這是一個Builder,而不是一個列表)與and列表,並希望將People構造提升到用於Reads的適用函子的以便您可以將其應用於這些參數。

例如,如果你的People類型是這樣的:

case class People(names: Set[Id], home: String) 

你可以寫:

implicit val PeopleReads: Reads[People] = (
    (__ \ "names").read[Set[Id]] and 
    (__ \ "home").read[String] 
)(People) 

在你的情況,不過,對於People的構造函數有一個參數,而你沒有使用and,所以你沒有Builder[Reads[Set[Id] ~ String],你剛剛有一個普通的舊Reads[Set[Id]]

這是很好的,因爲這意味着你不必奇怪適用函子的語法,所有你需要的是map

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

大功告成。

+0

'__'與'JsPath'相同嗎?如果是這樣,是__'首選?如果是這樣,爲什麼? –

+2

是的,這只是一個別名,它旨在提供特定種類的DSL。這不是我通常親自進入的事情,但是在這種情況下,我碰巧喜歡這種語法。我認爲除此之外,還有其他的「首選」 - 你可以拿走它或者放棄它。 –

+0

您能否多說'...讀[Set [Id]]。map(People)'? 「人」功能的簽名是什麼?我知道'People'是一個case類,但我理解map:'M [A] .map(A => B):M [B]' –