Синтаксический анализ Json Array в игровой структуре JsObject
У меня есть следующий Json:
{
"web-category" : "macaroons",
"sub-categories" : [
{ "name" : "pink" },
{ "name" : "blue" },
{ "name" : "green" }
]
}
Я получил его в Play как JsObject. Поэтому я могу успешно выполнить следующее:
//(o is the JsObject)
val webCat:Option[String] = (o \ "web-category").asOpt[String]
println(webCat.toString)
>> Some(macaroons)
До сих пор так хорошо. Но как мне получить доступ к массиву объектов Json? У меня это...
val subCats:Option[JsArray] = (o \ "sub-categories").asOpt[JsArray]
println(subCats.toString)
>> Some([{"name" : "blue"},{"name" : "green"},{"name" : "pink"}])
но мне нужно взять JsArray и получить список всех имен примерно так:
List("blue", "green", "pink")
Не знаю, как получить доступ к JsArray таким образом.
спасибо за помощь в этом.
Ответы
Ответ 1
Я бы сказал, что как правило, рекомендуется как можно раньше перейти от JSON-land к родному-w60 -представлению. Если obj
является вашим JsObject
, например, вы можете написать это:
val subCategories = (obj \ "sub-categories").as[List[Map[String, String]]]
val names = subCategories.map(_("name"))
Или даже:
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)
И затем:
obj.as[Category]
Этот последний подход делает обработку ошибок еще более чистым (например, вы можете просто заменить as
на asOpt
на этом верхнем уровне) и прекрасно сочетается с другими экземплярами класса Reads
- если у вас есть JsArray
этих объекты, например, вы можете просто написать array.as[List[Category]]
и получить то, что ожидаете.
Ответ 2
Что сказал Питер, или:
(o \ "sub-categories" \\ "name").map(_.as[String]).toList
Ответ 3
Что-то вроде этого:
subCats.map( jsarray => jsarray.value.map(jsvalue => (jsvalue \ "name").as[String]).toList)
Обычно это возвращает Option[List[String]]