在播放框架 JsObject 中解析 Json 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22045385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:09:19  来源:igfitidea点击:

parsing a Json Array in play framework JsObject

jsonscalaplayframework-2.0

提问by Zuriar

I have the following Json:

我有以下 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:

我在 Play 中将它作为 JsObject 使用。所以我现在可以成功执行以下操作:

//(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...

到现在为止还挺好。但是如何访问数组 Json 对象呢?我有这个...

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:

但我需要的是获取 JsArray 并获取所有名称的列表,如下所示:

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

Don't know how to access the JsArray thusly.

不知道如何访问 JsArray。

my thanks for your help in this.

我感谢你在这方面的帮助。

采纳答案by Travis Brown

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 objis your JsObject, for example, you can write this:

我认为尽早从 JSON-land 迁移到原生 Scala-representation-land 通常是个好主意。例如,如果obj是你的JsObject,你可以这样写:

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 aswith asOptat this top level) and composes nicely with other Readstype class instances—if you have a JsArrayof these objects, for example, you can just write array.as[List[Category]]and get what you expect.

后一种方法使错误处理更加清晰(例如,您可以在此顶层替换aswith asOpt)并与其他Reads类型的类实例很好地组合——例如,如果您有JsArray这些对象中的一个,您就可以编写array.as[List[Category]]并获得您期望的内容。

回答by johanandren

What Peter said, or:

彼得所说的,或:

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

回答by Peter

Something like this:

像这样的东西:

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

This will normally return a Option[List[String]]

这通常会返回一个 Option[List[String]]