Есть ли JSON-эквивалент XQuery / XPath?

221

При поиске элементов в сложных массивах и хешах JSON, например:

[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [
            // etc.
        }]
    }
]

Есть ли какой-то язык запросов, который я могу использовать, чтобы найти предмет in [0].objects where id = 3?

Нафтули Кей
источник
нет, если вы не сделаете один. Оставьте запрос на сервере и используйте REST для получения только тех данных, которые вам нужны.
zzzzBov
5
+1 хорошая идея. Собираюсь написать это завтра ...
2
Не XPath, но я нашел JLinq довольно хорошим (который делает код читаемым как in(...).where(...).select(...)): hugoware.net/Projects/jLinq .
pimvdb
4
Это расстраивает, потому что есть много библиотек, но ничто не приближается к общепринятому стандарту. У нас есть библиотека, используемая сторонними организациями, поэтому нам нужно предоставить язык запросов, который широко известен и используется.
Дэвид Тилен
1
Конечно, вы можете использовать jsel - github.com/dragonworx/jsel - если у вас есть переменная, dataкоторая содержит ваш JSON-объект, вы должны написать: jsel(data).select("//*[@id=3]")и он вернет объект, содержащий ключ id, с 3.
Ali

Ответы:

122

Да, это называется JSONPath . Источник теперь на GitHub .

Он также интегрирован в DOJO .

Майк Кристенсен
источник
3
Ответ Брайана говорит о том, что модуль jsonQuery следует использовать вместо модуля jsonPath в dojo.
hugomg
5
Насколько это твердо? И я не могу найти версию на Java или C #, которая бы помешала нам.
Дэвид Тилен
2
Сайт, указанный здесь, предоставляет Javascript и PHP. Если вам нужна реализация Java, здесь есть такая
Матиас Ронге
2
Я должен отметить, что JSONPath не основан на формальной семантике XPath. JSONiq может быть лучшим вариантом.
wcandillon
1
@Paramaeleon Это прекрасно работает. Кстати, проект был перенесен на GitHub . Майк может захотеть добавить это к ответу, так как люди продолжают комментировать это.
Франклин Ю
21

Я думаю, что JSONQuery является надмножеством JSONPath и поэтому заменяет его в dojo . Тогда есть также RQL .

Из документации Dojo:

JSONQuery - это расширенная версия JSONPath с дополнительными функциями для обеспечения безопасности, простоты использования и полным набором инструментов запроса данных, включая фильтрацию, рекурсивный поиск, сортировку, сопоставление, выбор диапазона и гибкие выражения с сопоставлением подстановочных знаков и различными операторами.

JSONselect имеет другую точку зрения на этот вопрос (CSS-селектор, а не XPath) и имеет реализацию JavaScript .

Брайан Клозел
источник
4
Ссылка на github JSONQuery кажется мертвой. JSONSelect также имеет версию JavaScript.
Хенрик Аастед Серенсен
19

Другие известные мне альтернативы

  1. Спецификация JSONiq , которая задает два подтипа языков: один, который скрывает детали XML и обеспечивает синтаксис, подобный JS, и другой, который обогащает синтаксис XQuery конструкторами JSON и тому подобное. Zorba реализует JSONiq.
  2. Corona , основанная на MarkLogic, предоставляет интерфейс REST для хранения, управления и поиска XML, JSON, текстового и двоичного содержимого.
  3. MarkLogic 6 и более поздние версии предоставляют интерфейс REST, аналогичный Corona из коробки.
  4. MarkLogic 8 и более поздние версии поддерживают JSON как в среде XQuery, так и в среде JavaScript на стороне сервера. Вы можете применить XPath к нему.

НТН.

grtjn
источник
3
Теперь есть реализация JSONiq: Zorba 2.6 официально поддерживает ее.
Гизлен Фурни
Примечание. MarkLogic изначально сохраняет JSON начиная с версии 8 и позволяет напрямую применять к нему XPath.
grtjn
18

Подведем итоги некоторых текущих опций обхода / фильтрации данных JSON и приведем несколько примеров синтаксиса ...

  • JSPath
    .automobiles{.maker === "Honda" && .year > 2009}.model

  • json: select () (больше вдохновлено селекторами CSS)
    .automobiles .maker:val("Honda") .model

  • JSONPath (больше вдохновлен XPath)
    $.automobiles[?(@.maker='Honda')].model

Я думаю, что JSPath выглядит лучше, поэтому я собираюсь попробовать интегрировать его с моим приложением AngularJS + CakePHP.

(Первоначально я разместил этот ответ в другой ветке, но подумал, что он будет полезен и здесь.)

Саймон Ист
источник
Большое резюме и примеры, также из-за упоминания вдохновения, найденного в селекторах CSS или XPath.
Йохем Шуленклоппер
13

Попробуйте использовать JSPath

JSPath - это предметно-ориентированный язык (DSL), который позволяет вам перемещаться и находить данные в ваших документах JSON. Используя JSPath, вы можете выбирать элементы JSON для извлечения данных, которые они содержат.

JSPath для JSON похож на XPath для XML.

Он сильно оптимизирован как для Node.js, так и для современных браузеров.

dfilatov
источник
9

XQuery может использоваться для запроса JSON при условии, что процессор предлагает поддержку JSON. Это простой пример того, как BaseX может использоваться для поиска объектов с «id» = 1:

json:parse('[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [ "etc." ] }
    ]}
]')//value[.//id = 1]
Кристиан Грюн
источник
(6 лет спустя) Saxon будет запускать XQuery 3.1, который запрашивает JSON. Мой саксонский опыт использует jar-файл, запускаемый java. Есть модуль узла с именем saxon-java, но я не уверен, как это работает с json. И есть еще одна новинка от Saxonica под названием Saxon-JS.
Чарльз Росс
9

Есть ли какой-то язык запросов ...

JQ определяет J SON д язык uery , который очень похож на JSONPath - см https://github.com/stedolan/jq/wiki/For-JSONPath-users

... [который] я могу использовать, чтобы найти элемент в [0] .объектах, где id = 3?

Я предполагаю, что это означает: найти все объекты JSON под указанным ключом с id == 3, независимо от того, где объект может быть. Соответствующий JQ-запрос будет:

.[0].objects | .. | objects | select(.id==3)

где "|" является оператором канала (как в каналах командной оболочки), и где сегмент ".. | objects" соответствует "независимо от того, где объект может быть".

Основы jq в основном очевидны, интуитивно понятны или, по крайней мере, довольно просты, а большинство остальных легко понять, если вы вообще знакомы с каналами командной оболочки. JQ FAQ содержит ссылки на учебные пособия и тому подобное.

jq также похож на SQL в том, что он поддерживает операции CRUD, хотя процессор jq никогда не перезаписывает свой ввод. jq также может обрабатывать потоки объектов JSON.

При оценке языка запросов, ориентированного на JSON, вы можете рассмотреть два других критерия:

  • это поддерживает регулярные выражения? (JQ 1.5 имеет всестороннюю поддержку регулярных выражений PCRE)
  • это полный по Тьюрингу? (Ага)
вершина горы
источник
8

Defiant.js выглядит также довольно круто, вот простой пример:

var obj = {
        "car": [
            {"id": 10, "color": "silver", "name": "Volvo"},
            {"id": 11, "color": "red",    "name": "Saab"},
            {"id": 12, "color": "red",    "name": "Peugeot"},
            {"id": 13, "color": "yellow", "name": "Porsche"}
        ],
        "bike": [
            {"id": 20, "color": "black", "name": "Cannondale"},
            {"id": 21, "color": "red",   "name": "Shimano"}
        ]
    },
    search = JSON.search(obj, '//car[color="yellow"]/name');

console.log( search );
// ["Porsche"]

var reds = JSON.search(obj, '//*[color="red"]');

for (var i=0; i<reds.length; i++) {
    console.log( reds[i].name );
}
// Saab
// Peugeot
// Shimano
Epoc
источник
К сожалению, на данный момент не опубликовано на npm и требует ручной установки ...
Andrew Mao
7

Jsel великолепен и основан на реальном движке XPath. Он позволяет создавать выражения XPath для поиска любого типа данных JavaScript, а не только объектов (также строк).

Вы можете создавать собственные схемы и сопоставления, чтобы дать вам полный контроль над тем, как ваши данные доступны для движка XPath. Схема - это способ определения того, как элементы, дочерние элементы, атрибуты и значения узлов определяются в ваших данных. Затем вы можете создавать свои собственные выражения, чтобы удовлетворить.

Учитывая, что у вас есть переменная, dataкоторая содержит JSON из вопроса, вы можете использовать jsel для записи:

jsel(data).select("//*[@id=3]")

Это вернет любой узел с idатрибутом 3. Атрибут - это любое примитивное значение (строка, число, дата, регулярное выражение) внутри объекта.

Али
источник
6

ObjectPath - это язык запросов, похожий на XPath или JSONPath, но гораздо более мощный благодаря встроенным арифметическим вычислениям, механизмам сравнения и встроенным функциям. Смотрите синтаксис:

Найти в магазине все туфли красного цвета и по цене менее 50

$ .. обувь. * [цвет "красный" и цена <50]

Эла Беднарек
источник
Мне нравится первый пример на веб-сайте, и это здорово, что ObjectPath можно запускать в интерактивном, похожем на оболочку режиме, но мне нужно использовать ObjectPath в скрипте Python. Можете ли вы указать мне пример, показывающий, как использовать ObjectPath в качестве библиотеки? Я не могу найти ничего подобного на сайте.
piokuc
Пожалуйста, смотрите раздел об использовании Python на github . Мы добавим это на сайт - это действительно трудно найти в данный момент. Если вам нужна дополнительная помощь, вы можете опубликовать вопрос в группе Google .
Эла Беднарек
Спасибо, Эла, примеры, добавленные на странице github, - это именно то, что нужно.
piokuc
4

@Naftule - с помощью «defiant.js» можно запрашивать структуру JSON с помощью выражений XPath. Проверьте этот оценщик, чтобы получить представление о том, как это работает:

http://www.defiantjs.com/#xpath_evaluator

В отличие от JSONPath, «defiant.js» обеспечивает полномасштабную поддержку синтаксиса запросов - XPath для структур JSON.

Исходный код defiant.js можно найти здесь:
https://github.com/hbi99/defiant.js

Хакан Билгин
источник
3

JMESPath, кажется, очень популярен в наши дни (с 2020 года) и решает ряд проблем с JSONPath. Это доступно для многих языков.

JLH
источник
1

Если вы похожи на меня и хотите просто выполнять поиск по пути, но не заботитесь о реальном XPath, lodash _.get()может работать. Пример из документации lodash:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, ['a', '0', 'b', 'c']);
// → 3

_.get(object, 'a.b.c', 'default');
// → 'default'
adittes
источник
К сожалению, эта функция может возвращать только один результат, она не поддерживает извлечение массива совпадающих элементов, где другие библиотеки сияют.
Саймон Ист
0

Попробуйте это - https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java

Это очень простая реализация в аналогичной строке xpath для xml. Это имена как jpath.

Сатьяджит Пол
источник
1
Этот вопрос отмечен тегом javascript, но эта библиотека предназначена для java
tripleee
Он также имеет версию Javascript - github.com/satyapaul/jpath/blob/master/jpath.js Вот он, git домашняя страница проекта - github.com/satyapaul/jpath
Сатьяджит Пол