Составить выражение JSONpath, чтобы оно получало только определенное значение? - PullRequest
3 голосов
/ 27 мая 2010

У меня есть несколько 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"
            }
        ]
    }
}

Я бы хотел получить только содержимое "p" для элемента div с классом "sT". Я хотел бы использовать цикл и делать что-то вроде этого:

var arrayOfResults = $.results..div.p 

не работает, потому что я хочу получить только значение p для элемента div с классом "sT".

Итак, как мне построить мой JSONpath, чтобы он извлекал массив из p-элементов, которые содержатся в классе divs "sT".

Спасибо !!

Ответы [ 3 ]

10 голосов
/ 29 мая 2010

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"

Так что используйте вышеприведенное выражение, и у вас все получится! Функция фильтра выглядит мощной, так что, вероятно, стоит изучить ее возможности!

1 голос
/ 14 января 2014

Вместо использования сложного, нестандартного стиля запроса, вы можете использовать DefiantJS (http://defiantjs.com),, который расширяет глобальный объект JSON с помощью метода «поиск» - с помощью которого вы можете запрашивать структуры JSON с помощью стандартизированные запросы XPath. Этот метод возвращает совпадения в массиве (пустой массив, если совпадений не найдено).

Вот рабочий код 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 Evaluator:
http://defiantjs.com/#xpath_evaluator

0 голосов
/ 01 апреля 2016

попробуйте

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

...