如何编写一个JSONpath表达式以仅检索特定值?

3

我有一些JSON数据,以下是其中的一小部分:

{
    "results": {
        "div": [
            {
                "class": "sylEntry",
                "div": [
                    {
                        "class": "sT",
                        "id": "sOT",
                        "p": "Mon 11/17, Computer work time"
                    },
                    {
                        "class": "des",
                        "id": "dOne",
                        "p": "All classes Siebel 0218"
                    }
                ],
                "id": "sylOne"
            }
        ]
    }
}

我希望只获取类名为"sT"
元素中的"p"内容。我想使用循环,做类似这样的事情:
var arrayOfResults = $.results..div.p 

这段代码无法正常工作,因为我只想获取类名为 "sT" 的 div 元素中的 p 值。

那么我该如何构造我的 JSONpath 以便检索包含在类名为 "sT" 的 div 中的 p 元素数组。

谢谢!


1
这个建议对你有用吗?只是友好的奖励提醒 :-D - jasonmp85
太棒了!!和惊人的东西一起运作了! - Alex
3个回答

10

概念

JSONPath 显然有一个筛选语法,允许您在表达式中插入任意的 Javascript 以进行匹配或过滤。它还使用@作为当前节点的快捷方式。将这两个东西结合起来的示例看起来像这样:

$..book[?(@.price<10)] // 过滤所有价格小于 10 的书籍

所以这可能是你想要在这里使用的。

解决方案

为了测试我心目中的查询,我修改了JSONPath's repo中的jsonpath-test-js.html文件以测试你的数据。你可以将我的示例复制粘贴到一个 HTML 文件中,并在浏览器中加载它。

他们的测试套件有一个包含字段op的对象数组。 o 包含要操作的原始数据,而 p 包含要应用于 o 的 JSONPath 表达式数组。它循环遍历所有这些对并将所有的 p 应用于它们各自的 o,并打印出结果。虽然不像简单的 REPL 那么方便,但它足以胜任。

这是我想出的内容:

<html>
<head>
<title> JSONPath - Tests (js)</title>
<script type="text/javascript" src="http://www.json.org/json.js"></script>
<script type="text/javascript"
        src="http://jsonpath.googlecode.com/svn/trunk/src/js/jsonpath.js">
</script>
</head>
<body>
<pre>
<script type="text/javascript">
var out = "", tests = 
[ { "o": { "results" : {  "div" : [  {  "clazz": "sylEntry",
           "id": "sylOne",  "div": [  {  "clazz": "sT",  "id": "sOT",
           "p": "Mon 11/17, Computer work time"  },  {  "clazz": "des",
           "id": "dOne",  "p": "All classes Siebel 0218"  }  ]  }  ]  }  },
    "p": ["$.results..div[?(@.clazz=='sT')].p", // my suggestion expression
          "$.results..div[*].p"]},             // your question's expression
];

function evaluate($, p) {
  var res = eval(p);
  return res != null ? res.toJSONString() : null;
}

for (var i=0; i<tests.length; i++) {
   var pathes;
   for (var j=0; j<tests[i].p.length; j++) {
      pre = ">";
      if (pathes = jsonPath(tests[i].o, tests[i].p[j], {resultType: "PATH"}))
         for (var k=0; k<pathes.length; k++) {
            out += pre + " " + pathes[k] +
                   " = " + evaluate(tests[i].o, pathes[k]) + "\n";
            pre = " ";
         }
      }
      out += "<hr/>";
   }
   document.write(out);
  </script>
</pre>
</body>
</html>

请注意,这将首先打印我的查询表达式的结果,然后再打印你的结果,以便我们可以比较它们的产生的内容。
以下是它产生的输出:
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
  $['results']['div'][0]['div'][4]['p'] = "All classes Siebel 0218"

因此,筛选表达式中的正确运算符是==,这意味着您的正确表达式是:

$.results..div[?(@.class=='sT')].p

然而,我发现一个不幸的问题(至少在JSONPath的Javascript实现中存在):在上述查询中使用单词"class"会导致以下结果:
SyntaxError: jsonPath: Parse error: _v.class=='sT'

我唯一的猜测是,某处调用了eval来实际评估JSONPath表达式。 class是Javascript中的保留字,因此会导致问题。让我们尝试使用@.class的替代语法:

$.results..div[?(@.['class']=='sT')].p

结果:

> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
  $['results']['div'][0]['div'][5]['p'] = "All classes Siebel 0218"

所以使用上述表达式,你就可以顺利进行!过滤功能看起来很强大,因此探索其能力肯定是值得的!


1

不要使用难以理解的非标准查询样式,您可以使用DefiantJS(http://defiantjs.com),它扩展了全局对象JSON的方法“search”-您可以使用标准化的XPath查询查询JSON结构。此方法返回数组中的匹配项(如果未找到匹配项,则为空数组)。

以下是代码的工作JSfiddle;
http://jsfiddle.net/hbi99/sy2bb/

var data = {
       "results": {
          "div": {
             "class": "sylEntry",
             "id": "sylOne",
             "div": [
                {
                   "class": "sT",
                   "id": "sOT",
                   "p": "Mon 11/17, Computer work time"
                },
                {
                   "class": "des",
                   "id": "dOne",
                   "p": "All classes Siebel 0218"
                }
             ]
          }
       }
    },
    res = JSON.search( data, '//div[class="sT"]/p' );

console.log( res[0] );
// Mon 11/17, Computer work time

为了了解XPath及其工作原理,请查看此XPath评估器工具:
http://defiantjs.com/#xpath_evaluator

0

试试这个

JsonPath.with(jsonResponse).param("name", "getName").get("findAll { a -> a.name == name }")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接