[英]Retrieving a particular field inside objects in JsArray
我的 JSON 響應的一部分如下所示:
"resources": [{
"password": "",
"metadata": {
"updated_at": "20190806172149Z",
"guid": "e1be511a-eb8e-1038-9547-0fff94eeae4b",
"created_at": "20190405013547Z",
"url": ""
},
"iam": false,
"email": "<some mail id>",
"authentication": {
"method": "internal",
"policy_id": "Default"
}
}, {
"password": "",
"metadata": {
"updated_at": "20190416192020Z",
"guid": "6b47118c-f4c8-1038-8d93-ed6d7155964a",
"created_at": "20190416192020Z",
"url": ""
},
"iam": true,
"email": "<some mail id>",
"authentication": {
"method": "internal",
"policy_id": null
}
},
...
]
我正在使用 Play 框架提供的 Json 助手來解析這個 Json,如下所示:
val resources: JsArray = response("resources").as[JsArray]
現在我需要從resources
JsArray 中的所有這些對象中提取字段email
。 為此,我嘗試編寫一個 foreach 循環,例如:
for (resource <- resources) {
}
但是我收到錯誤Cannot resolve symbol foreach
<-
符號處的Cannot resolve symbol foreach
。 如何從JsArray
內的每個 JSON 對象中檢索特定字段,如email
使用Play JSON我總是使用case classes
。 所以你的例子看起來像:
import play.api.libs.json._
case class Resource(password: String, metadata: JsObject, iam: Boolean, email: String, authentication: JsObject)
object Resource {
implicit val jsonFormat: Format[Resource] = Json.format[Resource]
}
val resources: Seq[Resource] = response("resources").validate[Seq[Resource]] match {
case JsSuccess(res, _) => res
case errors => // handle errors , e.g. throw new IllegalArgumentException(..)
}
現在您可以以type-safe
方式訪問任何字段。
當然,您可以以相同的方式用case classes
替換JsObject
s - 如果您在我的回答中需要這個,請告訴我。
但在您的情況下,因為您只需要email
所以不需要:
resources.map(_.email) // returns Seq[String]
所以就像@pme 說你應該使用 case 類一樣,它們應該是這樣的:
import java.util.UUID
import play.api.libs.json._
case class Resource(password:String, metadata: Metadata, iam:Boolean, email:UUID, authentication:Authentication)
object Resource{
implicit val resourcesImplicit: OFormat[Resource] = Json.format[Resource]
}
case class Metadata(updatedAt:String, guid:UUID, createdAt:String, url:String)
object Metadata{
implicit val metadataImplicit: OFormat[Metadata] = Json.format[Metadata]
}
case class Authentication(method:String, policyId: String)
object Authentication{
implicit val authenticationImplicit: OFormat[Authentication] =
Json.format[Authentication]
}
您還可以使用寫入和讀取而不是 OFormat,或自定義寫入和讀取,我使用 OFormat 是因為它不那么冗長。
然后當你得到你的回應時,你驗證它們,你可以按照@pme 所說的方式驗證它們,或者我這樣做的方式:
val response_ = response("resources").validate[Seq[Resource]]
response_.fold(
errors => Future.succeful(BadRequest(JsError.toJson(errors)),
resources => resources.map(_.email))// extracting emails from your objects
???
)
所以在這里你在 Json 無效時做一些事情,當 Json 有效時做另一件事,行為與 pme 所做的相同,只是在我看來更優雅一點
假設您的 json 如下所示:
val jsonString =
"""
|{
| "resources": [
| {
| "password": "",
| "metadata": {
| "updated_at": "20190806172149Z",
| "guid": "e1be511a-eb8e-1038-9547-0fff94eeae4b",
| "created_at": "20190405013547Z",
| "url": ""
| },
| "iam": false,
| "email": "<some mail id1>",
| "authentication": {
| "method": "internal",
| "policy_id": "Default"
| }
| },
| {
| "password": "",
| "metadata": {
| "updated_at": "20190416192020Z",
| "guid": "6b47118c-f4c8-1038-8d93-ed6d7155964a",
| "created_at": "20190416192020Z",
| "url": ""
| },
| "iam": true,
| "email": "<some mail id2>",
| "authentication": {
| "method": "internal",
| "policy_id": null
| }
| }
| ]
|}
""".stripMargin
你可以做:
(Json.parse(jsonString) \ "resources").as[JsValue] match{
case js: JsArray => js.value.foreach(x => println((x \ "email").as[String]))
case x => println((x \ "email").as[String])
}
或者:
(Json.parse(jsonString) \ "resources").validate[JsArray] match {
case s: JsSuccess[JsArray] => s.get.value.foreach(x => println((x \ "email").as[String]))
case _: JsError => arr().value //or do something else
}
兩者都適合我。
resources
是一個JsArray
,一種不提供.flatMap
的類型,因此不能在<-
右側使用以進行理解。
val emailReads: Reads[String] = (JsPath \ "email").reads[String]
val resourcesReads = Reads.seqReads(emailReads)
val r: JsResult[Seq[String]] = resources.validate(resources reads)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.