使用Play JSON查询并查找JSON元素值的路径

时间:2016-10-20 07:08:12

标签: scala playframework jsonpath

我在Scala中使用Play Framework。我有一个上游服务器返回的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]内的不同索引上。我如何解决是否

的问题
  1. 密钥存在于从上游服务器获取的JSON中。
  2. 找到密钥的路径,因此我可以根据相同的路径找到其他密钥。这是一个反向查找问题。
  3. 我目前只能考虑获取$.suspendData.d[1]然后循环以查找是否存在此类属性。 同样,我无法通过JsPath找到一种正确的方法。我知道JsonPath等价,但无法通过现有的Play JSON支持找到正确的方法。

2 个答案:

答案 0 :(得分:1)

您可以使用\上定义的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"]]]]
)

答案 1 :(得分:0)

简单的递归,可能不那么有效,但有效:

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)