Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parsing a Json Array in play framework JsObject

I have the following Json:

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

I have got it in Play as a JsObject. So I can now successfully do the following:

//(o is the JsObject)  val webCat:Option[String] = (o \ "web-category").asOpt[String]  println(webCat.toString)  >> Some(macaroons) 

So far, so good. But how do I access the array Json objects? I have this...

val subCats:Option[JsArray] = (o \ "sub-categories").asOpt[JsArray]  println(subCats.toString)  >> Some([{"name" : "blue"},{"name" : "green"},{"name" : "pink"}]) 

but what I need is to take the JsArray and get a List of all the names something like this:

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

Don't know how to access the JsArray thusly.

my thanks for your help in this.

like image 255
Zuriar Avatar asked Feb 26 '14 15:02

Zuriar


People also ask

How do I parse a JSON file?

Example - Parsing JSONUse the JavaScript function JSON.parse() to convert text into a JavaScript object: const obj = JSON.parse('{"name":"John", "age":30, "city":"New York"}'); Make sure the text is in JSON format, or else you will get a syntax error.

What is JSONPath parse?

JSONPath is an expression language to parse JSON data. It's very similar to the XPath expression language to parse XML data. The idea is to parse the JSON data and get the value you want.

What is a JSValue?

You use the JSValue class to convert basic values, such as numbers and strings, between JavaScript and Objective-C or Swift representations to pass data between native code and JavaScript code.


2 Answers

I'd argue that it's generally a good idea to move from JSON-land to native-Scala-representation-land as early as possible. If obj is your JsObject, for example, you can write this:

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

Or even:

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) 

And then:

obj.as[Category] 

This latter approach makes error handling even cleaner (e.g. you can just replace as with asOpt at this top level) and composes nicely with other Reads type class instances—if you have a JsArray of these objects, for example, you can just write array.as[List[Category]] and get what you expect.

like image 106
Travis Brown Avatar answered Sep 21 '22 04:09

Travis Brown


What Peter said, or:

(o \ "sub-categories" \\ "name").map(_.as[String]).toList 
like image 40
johanandren Avatar answered Sep 22 '22 04:09

johanandren