web-dev-qa-db-de.com

Analysieren eines Json-Arrays im Play Framework JsObject

Ich habe folgenden Json:

{
  "web-category" : "macaroons",
  "sub-categories" : [
     { "name" : "pink" },
     { "name" : "blue" },
     { "name" : "green" }
  ]

}

Ich habe es als JsObject im Spiel. So kann ich nun erfolgreich folgendes machen:

//(o is the JsObject)

val webCat:Option[String] = (o \ "web-category").asOpt[String]

println(webCat.toString)

>> Some(macaroons)

So weit, ist es gut. Aber wie greife ich auf die Array-Json-Objekte zu? Ich habe das...

val subCats:Option[JsArray] = (o \ "sub-categories").asOpt[JsArray]

println(subCats.toString)

>> Some([{"name" : "blue"},{"name" : "green"},{"name" : "pink"}])

aber ich muss das JsArray nehmen und eine Liste aller Namen erhalten, die ungefähr so ​​aussehen:

List("blue", "green", "pink")

Ich weiß nicht, wie ich auf diese Weise auf das JsArray zugreifen soll.

ich danke Ihnen für Ihre Hilfe.

34
Zuriar

Ich würde argumentieren, dass es im Allgemeinen eine gute Idee ist, so früh wie möglich vom JSON-Land zum Scala-Repräsentationsland zu wechseln. Wenn obj beispielsweise Ihr JsObject ist, können Sie Folgendes schreiben:

val subCategories = (obj \ "sub-categories").as[List[Map[String, String]]]

val names = subCategories.map(_("name"))

Oder auch:

case class Category(name: String, subs: List[String])

import play.api.libs.functional.syntax._

implicit val categoryReader = (
  (__ \ "web-category").read[String] and
  (__ \ "sub-categories").read[List[Map[String, String]]].map(_.map(_("name")))
)(Category)

Und dann:

obj.as[Category]

Dieser letztere Ansatz macht die Fehlerbehandlung noch übersichtlicher (z. B. können Sie as nur durch asOpt auf dieser obersten Ebene ersetzen) und lässt sich mit anderen Klasseninstanzen vom Typ Reads kombinieren, wenn Sie dies haben Ein JsArray dieser Objekte können Sie zum Beispiel einfach array.as[List[Category]] und bekomme was du erwartest.

32
Travis Brown

Was Peter gesagt hat, oder:

(o \ "sub-categories" \\ "name").map(_.as[String]).toList
10
johanandren

Etwas wie das:

subCats.map( jsarray => jsarray.value.map(jsvalue => (jsvalue \ "name").as[String]).toList)

Dies wird normalerweise ein Option[List[String]]

4
Peter