概念
JSONPath 显然有一个筛选语法,允许您在表达式中插入任意的 Javascript 以进行匹配或过滤。它还使用@
作为当前节点的快捷方式。将这两个东西结合起来的示例看起来像这样:
$..book[?(@.price<10)] // 过滤所有价格小于 10 的书籍
所以这可能是你想要在这里使用的。
解决方案
为了测试我心目中的查询,我修改了JSONPath's repo中的jsonpath-test-js.html文件以测试你的数据。你可以将我的示例复制粘贴到一个 HTML 文件中,并在浏览器中加载它。
他们的测试套件有一个包含字段o
和p
的对象数组。 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"
所以使用上述表达式,你就可以顺利进行!过滤功能看起来很强大,因此探索其能力肯定是值得的!