Concepts
JSONPath, очевидно, имеет синтаксис фильтра, который позволяет вам вставлять произвольный Javascript в выражение для соответствия или фильтрации. Он также использует @
в качестве ярлыка для текущего узла. Их пример объединения этих двух вещей выглядит следующим образом:
$ .. book [? (@. Price <10)] // отфильтровать все
книги дешевле 10 </p>
Так что это, вероятно, то, что вы хотите использовать здесь.
Решение
Чтобы проверить запрос, который я имел в виду, я изменил файл jsonpath-test-js.html в репозиторий JSONPath для проверки ваших данных. Вы можете скопировать и вставить мой образец в файл HTML и просто загрузить его в браузер.
В их тестовом наборе есть массив объектов с полями с именами o
и p
. o
содержит исходные данные для работы, в то время как p
содержит массив выражений JSONPath для применения к o
. Он проходит по всем этим парам и применяет все p
s к соответствующим o
s, распечатывая результат. Не так удобно, как простой REPL, но это подойдет.
Вот что я придумал:
<code><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>
Обратите внимание, что это сначала напечатает результаты моего выражения запроса, а затем напечатает ваши результаты, чтобы мы могли сравнить, что они производят.
Вот вывод, который он производит:
> $['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): использование слова «класс» в приведенном выше запросе приводит к следующему:
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"
Так что используйте вышеприведенное выражение, и у вас все получится! Функция фильтра выглядит мощной, так что, вероятно, стоит изучить ее возможности!