web-dev-qa-db-fra.com

analyse d'un tableau Json dans le cadre de jeu JsObject

J'ai le Json suivant:

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

}

Je l'ai dans Play en tant que JsObject. Je peux donc maintenant réussir les opérations suivantes:

//(o is the JsObject)

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

println(webCat.toString)

>> Some(macaroons)

Jusqu'ici tout va bien. Mais comment accéder aux objets Json du tableau? J'ai ceci...

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

println(subCats.toString)

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

mais ce dont j'ai besoin est de prendre le JsArray et d'obtenir une liste de tous les noms quelque chose comme ceci:

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

Je ne sais pas comment accéder ainsi au JsArray.

merci pour votre aide.

34
Zuriar

Je dirais que c'est généralement une bonne idée de passer du JSON-land au native-Scala-representation-land le plus tôt possible. Si obj est votre JsObject, par exemple, vous pouvez écrire ceci:

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

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

Ou même:

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)

Puis:

obj.as[Category]

Cette dernière approche rend la gestion des erreurs encore plus propre (par exemple, vous pouvez simplement remplacer as par asOpt à ce niveau supérieur) et se compose bien avec d'autres instances de classe de type Reads - si vous avez un JsArray de ces objets, par exemple, vous pouvez simplement écrire array.as[List[Category]] et obtenez ce que vous attendez.

32
Travis Brown

Ce que Pierre a dit, ou:

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

Quelque chose comme ça:

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

Cela retournera normalement un Option[List[String]]

4
Peter