Existe-t-il un équivalent JSON de XQuery / XPath?

221

Lorsque vous recherchez des éléments dans des tableaux et hachages JSON complexes, comme:

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

Existe-t-il une sorte de langage de requête que je peux utiliser pour trouver un article in [0].objects where id = 3?

Naftuli Kay
la source
sauf si vous en faites un. Laissez la requête au serveur et utilisez REST pour obtenir uniquement les données dont vous avez besoin.
zzzzBov
5
+1 bonne idée. Je vais écrire ça demain…
2
Pas XPath, mais j'ai trouvé JLinq assez bon (ce qui rend le code semblable à celui-ci in(...).where(...).select(...)): hugoware.net/Projects/jLinq .
pimvdb
4
C'est frustrant car il y a beaucoup de bibliothèques, mais rien n'approche d'une norme communément acceptée. Nous avons une bibliothèque utilisée par des tiers, nous devons donc fournir un langage de requête largement connu et utilisé.
David Thielen
1
Bien sûr, vous pouvez utiliser jsel - github.com/dragonworx/jsel - étant donné que vous avez une variable dataqui contient votre objet JSON, vous écririez : jsel(data).select("//*[@id=3]")et cela retournerait l'objet contenant la clé id avec 3.
Ali

Réponses:

122

Oui, ça s'appelle JSONPath . La source est maintenant sur GitHub .

Il est également intégré à DOJO .

Mike Christensen
la source
3
La réponse de Brian suggère que le module jsonQuery devrait être utilisé à la place du module jsonPath dans dojo.
hugomg
5
Est-ce solide? Et je ne trouve pas de version Java ou C # qui est un tueur de deal pour nous.
David Thielen
2
Le site lié ici fournit Javascript et PHP. Si vous avez besoin d'une implémentation Java, il y en a une ici: code.google.com/p/json-path
Matthias Ronge
2
Je dois mentionner que JSONPath n'est pas basé sur la sémantique formelle XPath. JSONiq pourrait être une meilleure option.
wcandillon
1
@Paramaeleon Cela fonctionne très bien. Soit dit en passant , le projet a été migré vers GitHub . Mike voudra peut-être ajouter cela à la réponse, car les gens continuent de commenter à ce sujet.
Franklin Yu
21

Je pense que JSONQuery est un sur-ensemble de JSONPath et le remplace donc dans dojo . Ensuite, il y a aussi RQL .

De la documentation Dojo:

JSONQuery est une version étendue de JSONPath avec des fonctionnalités supplémentaires pour la sécurité, la facilité d'utilisation et un ensemble complet d'outils d'interrogation de données, notamment le filtrage, la recherche récursive, le tri, le mappage, la sélection de plage et des expressions flexibles avec des comparaisons de chaînes génériques et divers opérateurs.

JSONselect a un autre point de vue sur la question (comme un sélecteur CSS, plutôt que XPath) et a une implémentation JavaScript .

Brian Clozel
la source
4
Le lien github JSONQuery semble être mort. JSONSelect a également une version JavaScript maintenant.
Henrik Aasted Sørensen
19

D'autres alternatives que je connais sont

  1. Spécification JSONiq , qui spécifie deux sous-types de langues: une qui masque les détails XML et fournit une syntaxe de type JS, et une qui enrichit la syntaxe XQuery avec des constructeurs JSON et autres. Zorba implémente JSONiq.
  2. Corona , qui s'appuie sur MarkLogic, fournit une interface REST pour le stockage, la gestion et la recherche de contenu XML, JSON, texte et binaire.
  3. MarkLogic 6 et versions ultérieures fournissent une interface REST similaire à Corona prête à l'emploi.
  4. MarkLogic 8 et versions ultérieures prennent en charge JSON en mode natif dans leur environnement JavaScript XQuery et côté serveur. Vous pouvez y appliquer XPath.

HTH.

grtjn
la source
3
Il existe désormais une implémentation JSONiq: Zorba 2.6 la prend officiellement en charge.
Ghislain Fourny
Remarque: MarkLogic stocke JSON en mode natif à partir de la version 8 et permet d'appliquer directement XPath dessus.
grtjn
18

Pour résumer certaines des options actuelles de traversée / filtrage des données JSON, et fournir quelques exemples de syntaxe ...

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

  • json: select () (inspiré plus des sélecteurs CSS)
    .automobiles .maker:val("Honda") .model

  • JSONPath (inspiré plus par XPath)
    $.automobiles[?(@.maker='Honda')].model

Je pense que JSPath est le plus joli, donc je vais essayer de l'intégrer avec mon application AngularJS + CakePHP.

(J'ai initialement publié cette réponse dans un autre sujet, mais j'ai pensé qu'elle serait utile ici également.)

Simon East
la source
Grand résumé et exemples, également en raison de la mention de l'inspiration trouvée dans les sélecteurs CSS ou XPath.
Jochem Schulenklopper
13

Essayez d'utiliser JSPath

JSPath est un langage spécifique au domaine (DSL) qui vous permet de naviguer et de trouver des données dans vos documents JSON. À l'aide de JSPath, vous pouvez sélectionner des éléments de JSON afin de récupérer les données qu'ils contiennent.

JSPath pour JSON comme un XPath pour XML.

Il est fortement optimisé à la fois pour Node.js et les navigateurs modernes.

dfilatov
la source
9

XQuery peut être utilisé pour interroger JSON, à condition que le processeur offre une prise en charge JSON. Voici un exemple simple d'utilisation de BaseX pour rechercher des objets avec "id" = 1:

json:parse('[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [ "etc." ] }
    ]}
]')//value[.//id = 1]
Christian Grün
la source
(6 ans plus tard) Saxon exécutera XQuery 3.1, qui interroge JSON. Mon expérience saxonne utilise le fichier jar géré par java. Il existe un module de nœud nommé saxon-java mais je ne sais pas comment cela fonctionne avec json. Et il y a une autre nouveauté de Saxonica appelée Saxon-JS.
charles ross
9

Existe-t-il une sorte de langage de requête ...

JQ définit un J SON q langage uery qui est très similaire à JSONPath - voir https://github.com/stedolan/jq/wiki/For-JSONPath-users

... [que] je peux utiliser pour trouver un élément dans [0] .objects où id = 3?

Je suppose que cela signifie: recherchez tous les objets JSON sous la clé spécifiée avec id == 3, peu importe où l'objet peut être. Une requête jq correspondante serait:

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

où "|" est l'opérateur pipe (comme dans les pipes shell de commande), et où le segment ".. | objets" correspond à "peu importe où l'objet peut être".

Les bases de jq sont largement évidentes ou intuitives ou du moins assez simples, et la plupart du reste est facile à comprendre si vous êtes familier avec les canaux de shell de commande. La FAQ jq contient des pointeurs vers des didacticiels et autres.

jq est également similaire à SQL en ce qu'il prend en charge les opérations CRUD, bien que le processeur jq n'écrase jamais son entrée. jq peut également gérer des flux d'entités JSON.

Deux autres critères que vous souhaiterez peut-être prendre en compte pour évaluer un langage de requête orienté JSON sont:

  • prend-il en charge les expressions régulières? (jq 1.5 a un support complet pour regex PCRE)
  • est-ce que Turing est complet? (oui)
de pointe
la source
8

Defiant.js a également l'air plutôt cool, voici un exemple simple:

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
la source
Malheureusement, non publié sur npm pour le moment et nécessite une installation manuelle ...
Andrew Mao
7

Jsel est génial et est basé sur un véritable moteur XPath. Il vous permet de créer des expressions XPath pour trouver n'importe quel type de données JavaScript, pas seulement des objets (des chaînes aussi).

Vous pouvez créer des schémas et des mappages personnalisés pour vous donner un contrôle complet sur la façon dont vos données peuvent être parcourues par le moteur XPath. Un schéma est un moyen de définir la façon dont les éléments, les enfants, les attributs et les valeurs des nœuds sont définis dans vos données. Ensuite, vous pouvez créer vos propres expressions en fonction.

Étant donné que vous avez appelé une variable dataqui contient le JSON de la question, vous pouvez utiliser jsel pour écrire:

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

Cela renverra n'importe quel nœud avec un idattribut de 3. Un attribut est une valeur primitive (chaîne, nombre, date, expression régulière) dans un objet.

Ali
la source
6

ObjectPath est un langage de requête similaire à XPath ou JSONPath, mais beaucoup plus puissant grâce aux calculs arithmétiques intégrés, aux mécanismes de comparaison et aux fonctions intégrées. Voir la syntaxe:

Retrouvez dans la boutique toutes les chaussures de couleur rouge et prix inférieur à 50

$ .. chaussures. * [la couleur est "rouge" et prix <50]

Ela Bednarek
la source
J'aime le premier exemple sur le site Web et c'est génial qu'ObjectPath puisse être exécuté en mode interactif, comme un shell, mais ce que je recherche, c'est d'utiliser ObjectPath dans un script Python. Pouvez-vous me montrer un exemple montrant comment utiliser ObjectPath comme bibliothèque? Je ne trouve rien de tel sur le site Web.
piokuc
Veuillez consulter la section sur l'utilisation de Python sur github . Nous ajouterons cela au site Web - c'est en effet difficile à trouver pour le moment. Si vous avez besoin d'aide, vous pouvez publier une question sur le groupe Google .
Ela Bednarek
Merci, Ela, les exemples ajoutés sur la page github sont exactement ce qu'il fallait.
piokuc
4

@Naftule - avec "defiant.js", il est possible d'interroger une structure JSON avec des expressions XPath. Consultez cet évaluateur pour avoir une idée de son fonctionnement:

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

Contrairement à JSONPath, "defiant.js" offre la prise en charge à grande échelle de la syntaxe de requête - de XPath sur les structures JSON.

Le code source de defiant.js peut être trouvé ici:
https://github.com/hbi99/defiant.js

Hakan Bilgin
la source
3

JMESPath semble être très populaire de nos jours (à partir de 2020) et résout un certain nombre de problèmes avec JSONPath. Il est disponible dans de nombreuses langues.

jlh
la source
1

Si vous êtes comme moi et que vous voulez simplement faire des recherches basées sur le chemin, mais que vous ne vous souciez pas du vrai XPath, lodash _.get()peut fonctionner. Exemple de documents 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
la source
Malheureusement, cette fonction ne peut renvoyer qu'un seul résultat, elle ne prend pas en charge la récupération d'un tableau d'éléments correspondants, où les autres bibliothèques brillent.
Simon East