我有包含表示兩種不同類型的實體JsValue
對象JsArray
- 它們中的一些代表節點,另一部分表示邊緣。播放的Json API:轉換一個JsArray到JsResult [序號[元件]]
在斯卡拉方面,已經有案例類Node
和Edge
超類型Element
。目標是將JsArray
(或Seq[JsValue]
)轉換爲包含Scala類型的集合,例如Seq[Element]
(=>包含Node
和Edge
類型的對象)。
我已經定義Read
爲的情況下的類:
implicit val nodeReads: Reads[Node] = // ...
implicit val edgeReads: Reads[Edge] = // ...
除此之外,還有一個Read
爲JsArray
本身的第一步:
implicit val elementSeqReads = Reads[Seq[Element]](json => json match {
case JsArray(elements) => ???
case _ => JsError("Invalid JSON data (not a json array)")
})
與問號的部分如果JsArray
的所有元素都是有效的節點和邊,則負責創建JsSuccess(Seq(node1, edge1, ...)
;如果不是,則創建JsError
。
但是,我不知道如何以優雅的方式做到這一點。
的邏輯節點區分和邊緣可以這個樣子:
def hasType(item: JsValue, elemType: String) =
(item \ "elemType").asOpt[String] == Some(elemType)
val result = elements.map {
case n if hasType(n, "node") => // use nodeReads
case e if hasType(e, "edge") => // use edgeReads
case _ => JsError("Invalid element type")
}
的事情是,我不知道如何在這一點上處理nodeReads
/edgeReads
。當然,我可以直接調用他們的validate
方法,但result
的類型爲Seq[JsResult[Element]]
。所以最終我將不得不檢查是否有任何JsError
對象並將它們以某種方式委託給頂端(請記住:一個無效的數組元素應該總體上導致JsError
)。如果沒有錯誤,我仍然必須根據result
生成JsSuccess[Seq[Element]]
。
也許最好避免調用validate
,而是暫時使用Read
實例。但我不知道如何在最後「合併」所有的Read
實例(例如,在簡單的例子類映射中,您有一堆調用JsPath.read
(返回Read
),最後validate
產生一個單一結果基於使用關鍵字and
連接的所有這些Read實例)。
編輯:有一點點的信息。
首先,我應該提到案件類別Node
和Edge
基本上具有相同的結構,至少現在是這樣。目前,單獨分類的唯一原因是爲了獲得更多的類型安全。
一個元件的JsValue
具有以下JSON-表示:
{
"id" : "aet864t884srtv87ae",
"type" : "node", // <-- type can be 'node' or 'edge'
"name" : "rectangle",
"attributes": [],
...
}
相應的情況下,類看起來像這樣(注意,我們上面已經看到的類型屬性是不類的屬性 - 相反,它由類的類型代表 - >Node
)。
case class Node(
id: String,
name: String,
attributes: Seq[Attribute],
...) extends Element
的Read
如下:
implicit val nodeReads: Reads[Node] = (
(__ \ "id").read[String] and
(__ \ "name").read[String] and
(__ \ "attributes").read[Seq[Attribute]] and
....
) (Node.apply _)
一切看起來爲Edge
相同,至少目前是這樣。
感謝您的快速回答。如果我沒有錯,JsValues之間沒有明確的映射(基於它們的「elemType」屬性,它可以是節點或邊緣)和案例類,而是通過反覆試驗做出決定,對嗎?我猜這是一個問題,因爲這兩個類(邊緣和節點)目前具有相同的結構(id,name,attributes,...),唯一的區別是類型本身。所以不會將邊緣和節點都轉換爲'Node'的實例? – alapeno
是的,但由於您沒有提供案例類或相關閱讀的結構,因此很難進一步幫助您。對於每個案例類的讀取可以只有在'elemType'具有正確的值 – Jean
我添加了一些信息,希望它有幫助。對'Read'中的elemType值的檢查也跨越了我的想法,但是這個值本身不應該是結果的一部分(參見上面的澄清)。 – alapeno