scala - 如何访问 JsValue 中的嵌套值?
问题描述
我有以下 Json 字符串
{
"results" : [
{
"address_components" : [
{
"long_name" : "1600",
"short_name" : "1600",
"types" : [ "street_number" ]
},
{
"long_name" : "Amphitheatre Parkway",
"short_name" : "Amphitheatre Pkwy",
"types" : [ "route" ]
},
{
"long_name" : "Mountain View",
"short_name" : "Mountain View",
"types" : [ "locality", "political" ]
}
]}]}
我使用以下语句解析它
val payload = Json.parse(results)
然后我得到以下结果
payload: play.api.libs.json.JsValue = {"results":[{"address_components":[{"long_name":"1600","short_name":"1600","types":["street_number"]},{"long_name":"Amphitheatre Parkway","short_name":"Amphitheatre Pkwy","types":["route"]},{"long_name":"Mountain View","short_name":"Mountain View","types":["locality","political"]}]}
当我尝试运行此命令时
val extract = (payload \ "results.address_components")
我得到以下输出
play.api.libs.json.JsLookupResult = JsUndefined('results.address_components' is undefined on object
如何访问元素“address_components”?
解决方案
我建议使用类似于GamingFelix 建议的案例类(替代方案在我的回答中的行下方),但如果您想知道为什么您的示例在这里不起作用,原因如下:
您没有正确遍历数组。给定以下 JSON:
{
"foo": [
{
"bar": 123,
"baz": "abc"
},
{
"bar": 456,
"baz": "def"
}
]
}
你会得到这样的所有bar
值:Json.parse(result) \ "foo" \\ "bar"
- 即,使用双反斜杠。您也可以将其链接在一起,例如(Json.parse(result) \\ "field1").map(_ \\ "field2")
等。
所以在你的例子中,如果你想要所有的long_name
字段,你会这样做:
import play.api.libs.json.Json
val json = Json.parse(
"""{"results" : [{"address_components" : [{"long_name" : "1600","short_name" : "1600","types" : [ "street_number" ]},{"long_name" : "Amphitheatre Parkway","short_name" : "Amphitheatre Pkwy","types" : [ "route" ]},{"long_name" : "Mountain View","short_name" : "Mountain View","types" : [ "locality", "political" ]}]},{"address_components" : [{"long_name" : "16400","short_name" : "1600","types" : [ "street_number" ]},{"long_name" : "Amphitheatre 5Parkway","short_name" : "Amphitheatre Pkwy","types" : [ "route" ]},{"long_name" : "Mounta6in View","short_name" : "Mountain View","types" : [ "locality", "political" ]}]}]}"""
)
(json \ "results" \\ "address_components").map(_ \\ "long_name")
这将返回一个数组数组,因为您要通过多个数组来获取您的值。如果你把 a.foreach(_.foreach(println))
放在最后,你会得到这个:
"1600"
"Amphitheatre Parkway"
"Mountain View"
"16400"
"Amphitheatre 5Parkway"
"Mounta6in View"
如果您很好奇,GamingFelix 几乎将这两种方法结合起来的建议并不是最好的——如果您只是将整个事情转换为案例类,则更容易理解正在发生的事情。此外,如果您为每个案例类创建一个伴随对象以放入格式化程序,而不是将所有内容保存在同一个格式化程序对象中,您将不需要在每次需要它们时显式导入格式化程序(Scala 会自动找到它们)。
这就是我的做法:
import play.api.libs.json.{Json, OFormat}
val json = Json.parse(
"""{"results" : [{"address_components" : [{"long_name" : "1600","short_name" : "1600","types" : [ "street_number" ]},{"long_name" : "Amphitheatre Parkway","short_name" : "Amphitheatre Pkwy","types" : [ "route" ]},{"long_name" : "Mountain View","short_name" : "Mountain View","types" : [ "locality", "political" ]}]},{"address_components" : [{"long_name" : "16400","short_name" : "1600","types" : [ "street_number" ]},{"long_name" : "Amphitheatre 5Parkway","short_name" : "Amphitheatre Pkwy","types" : [ "route" ]},{"long_name" : "Mounta6in View","short_name" : "Mountain View","types" : [ "locality", "political" ]}]}]}"""
)
case class MyClass(results: Seq[Result])
object MyClass {
implicit val format: OFormat[MyClass] = Json.format[MyClass]
}
case class Result(address_components: Seq[AddressComponent])
object Result {
implicit val format: OFormat[Result] = Json.format[Result]
}
case class AddressComponent(long_name: String, short_name: String, types: Seq[String])
object AddressComponent {
implicit val format: OFormat[AddressComponent] = Json.format[AddressComponent]
}
val model = json.as[MyClass] // `.as` is unsafe, use `.asOpt` or `.validate` or something like that in a real scenario
model.results.flatMap(_.address_components.map(_.long_name)) // get values out like you normally would in a class
推荐阅读
- android - 在 Extras Bundle 中传递 JSON 字符串的活动之间的通信是否正确?
- unity3d - Unity 中的 AR Core:如何更改表面着色器材质以支持法线贴图?
- google-apps-script - 谷歌脚本 - 根据条件发送自动电子邮件
- java - Angular项目在生产后显示白页
- c# - 计算二进制位图行中的黑色像素组
- javascript - JavaScript:转换对象结构
- sql - 带有用于列的存储桶的 SQL
- angular - 使用自定义字体pdfmake进行角度
- c# - ASP.NET UserManager InvalidOperationException 依赖注入
- amazon-web-services - 即使成功,如何获取 CodeDeploy 事件日志?