使用 Play JSON 查询并查找 JSON 元素值的路径
Query and find the path of an JSON element value with Play JSON
我正在将 Play Framework 与 Scala 结合使用。对于上游服务器返回的 JSON,我有以下结构。这只是一个代表
{
"key": "some-key",
"suspendData": {
"d": [
[
"arbitrary-objects/strings"
],
[
"random-value",
[
"arbitrary-objects/strings"
],
[
[
"value1",
"important-item",
[
"important-key-1"
],
"arbitrary-values/objects"
],
[
"value2",
"important-item-2",
[
"important-key-2"
]
]
]
]
]
}
}
我所知道的唯一事实是数据将位于 $.suspendData.d[1]
内的某处。我知道我要搜索的值是 important-key-1
。该值可以嵌套得更深,也可以位于 `d[1] 中的不同索引上。我该如何解决查找是否
的问题
- 从上游服务器获取的JSON中存在密钥
- 找到key的路径,所以我可以根据相同的路径找到其他的key。这是一个反向查找问题。
目前只能想到获取$.suspendData.d[1]
然后循环查找是否存在这样的属性。
同样,我找不到通过 JsPath 执行此操作的正确方法。我知道 JsonPath 等效项,但无法通过现有的 Play JSON 支持找到正确的方法。
您可以使用 JsValue
上定义的 \
方法并导航到 Json
中您想要的位置
为了得到你想做的事((json \ "suspendData") \ "d")(1)
这是 REPL 相同
的输出
scala> val json = Json.parse(str)
json: JsValue = {"key":"some-key","suspendData":{"d":[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]}}
scala> ((json \ "suspendData") \ "d")(1)
res32: JsLookupResult = JsDefined(
["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]
)
scala> val json = Json.parse(str)
json: JsValue = {"key":"some-key","suspendData":{"d":[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]}}
scala> (json \ "suspendData")
res34: JsLookupResult = JsDefined(
{"d":[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]}
)
scala> (json \ "suspendData") \ "d"
res35: JsLookupResult = JsDefined(
[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]
)
scala> ((json \ "suspendData") \ "d")(0)
res36: JsLookupResult = JsDefined(["arbitrary-objects/strings"])
scala> ((json \ "suspendData") \ "d")(1)
res37: JsLookupResult = JsDefined(
["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]
)
简单的递归,可能不是那么有效,但有效:
def findPath(key: String, path: JsPath, xs: JsValue): Option[JsPath] = {
xs match {
case o:JsObject =>
var res: Option[JsPath] = None
val it = o.fields.iterator
while (res.isEmpty && it.hasNext) {
val e = it.next()
res = findPath(key, path \ (e._1), e._2)
}
res
case JsString(x) if x==key =>
Some(path)
case JsArray(x) =>
var res: Option[JsPath] = None
val it = x.zipWithIndex.iterator
while (res.isEmpty && it.hasNext) {
val e = it.next()
res = findPath(key, path(e._2), e._1)
}
res
case _ => None
}
}
findPath("important-key-1", __, j)
findPath("important-key-2", __, j)
findPath("important-key-3", __, j)
findPath("some-key", __, j)
scala> res62: Option[play.api.libs.json.JsPath] = Some(/suspendData/d(1)(2)(0)(2)(0))
scala> res63: Option[play.api.libs.json.JsPath] = Some(/suspendData/d(1)(2)(1)(2)(0))
scala> res64: Option[play.api.libs.json.JsPath] = None
scala> res65: Option[play.api.libs.json.JsPath] = Some(/key)
我正在将 Play Framework 与 Scala 结合使用。对于上游服务器返回的 JSON,我有以下结构。这只是一个代表
{
"key": "some-key",
"suspendData": {
"d": [
[
"arbitrary-objects/strings"
],
[
"random-value",
[
"arbitrary-objects/strings"
],
[
[
"value1",
"important-item",
[
"important-key-1"
],
"arbitrary-values/objects"
],
[
"value2",
"important-item-2",
[
"important-key-2"
]
]
]
]
]
}
}
我所知道的唯一事实是数据将位于 $.suspendData.d[1]
内的某处。我知道我要搜索的值是 important-key-1
。该值可以嵌套得更深,也可以位于 `d[1] 中的不同索引上。我该如何解决查找是否
- 从上游服务器获取的JSON中存在密钥
- 找到key的路径,所以我可以根据相同的路径找到其他的key。这是一个反向查找问题。
目前只能想到获取$.suspendData.d[1]
然后循环查找是否存在这样的属性。
同样,我找不到通过 JsPath 执行此操作的正确方法。我知道 JsonPath 等效项,但无法通过现有的 Play JSON 支持找到正确的方法。
您可以使用 JsValue
上定义的 \
方法并导航到 Json
为了得到你想做的事((json \ "suspendData") \ "d")(1)
这是 REPL 相同
的输出scala> val json = Json.parse(str)
json: JsValue = {"key":"some-key","suspendData":{"d":[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]}}
scala> ((json \ "suspendData") \ "d")(1)
res32: JsLookupResult = JsDefined(
["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]
)
scala> val json = Json.parse(str)
json: JsValue = {"key":"some-key","suspendData":{"d":[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]}}
scala> (json \ "suspendData")
res34: JsLookupResult = JsDefined(
{"d":[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]}
)
scala> (json \ "suspendData") \ "d"
res35: JsLookupResult = JsDefined(
[["arbitrary-objects/strings"],["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]]
)
scala> ((json \ "suspendData") \ "d")(0)
res36: JsLookupResult = JsDefined(["arbitrary-objects/strings"])
scala> ((json \ "suspendData") \ "d")(1)
res37: JsLookupResult = JsDefined(
["random-value",["arbitrary-objects/strings"],[["value1","important-item",["important-key-1"],"arbitrary-values/objects"],["value2","important-item-2",["important-key-2"]]]]
)
简单的递归,可能不是那么有效,但有效:
def findPath(key: String, path: JsPath, xs: JsValue): Option[JsPath] = {
xs match {
case o:JsObject =>
var res: Option[JsPath] = None
val it = o.fields.iterator
while (res.isEmpty && it.hasNext) {
val e = it.next()
res = findPath(key, path \ (e._1), e._2)
}
res
case JsString(x) if x==key =>
Some(path)
case JsArray(x) =>
var res: Option[JsPath] = None
val it = x.zipWithIndex.iterator
while (res.isEmpty && it.hasNext) {
val e = it.next()
res = findPath(key, path(e._2), e._1)
}
res
case _ => None
}
}
findPath("important-key-1", __, j)
findPath("important-key-2", __, j)
findPath("important-key-3", __, j)
findPath("some-key", __, j)
scala> res62: Option[play.api.libs.json.JsPath] = Some(/suspendData/d(1)(2)(0)(2)(0))
scala> res63: Option[play.api.libs.json.JsPath] = Some(/suspendData/d(1)(2)(1)(2)(0))
scala> res64: Option[play.api.libs.json.JsPath] = None
scala> res65: Option[play.api.libs.json.JsPath] = Some(/key)