Esiste un equivalente JSON di XQuery / XPath?


221

Durante la ricerca di elementi in array e hash JSON complessi, come:

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

Esiste un tipo di linguaggio di query che posso usare per trovare un elemento in [0].objects where id = 3?


a meno che tu non ne faccia uno. Lasciare la query al server e utilizzare REST per ottenere solo i dati necessari.
zzzzBov,

5
+1 buona idea. Lo scrivo domani ...

2
Non XPath, ma ho trovato JLinq abbastanza buono (che rende il codice da leggere come in(...).where(...).select(...)): hugoware.net/Projects/jLinq .
pimvdb,

4
Questo è frustrante perché ci sono molte librerie là fuori, ma nulla si avvicina a uno standard comunemente accettato. Disponiamo di una libreria utilizzata da terze parti, pertanto è necessario fornire un linguaggio di query ampiamente conosciuto e utilizzato.
David Thielen,

1
Certo, puoi usare jsel - github.com/dragonworx/jsel - dato che hai una variabile datache contiene il tuo oggetto JSON, dovresti scrivere: jsel(data).select("//*[@id=3]")e restituirebbe l'oggetto contenente la chiave ID con 3.
Ali

Risposte:


122

Sì, si chiama JSONPath . La fonte è ora su GitHub .

È inoltre integrato in DOJO .


3
La risposta di Brian suggerisce che il modulo jsonQuery dovrebbe essere usato al posto del modulo jsonPath in dojo.
hugomg,

5
Quanto è solido questo? E non riesco a trovare una versione Java o C # che è un affare per noi.
David Thielen,

2
Il sito collegato qui fornisce Javascript e PHP. Se hai bisogno di un'implementazione Java, ce n'è una qui: code.google.com/p/json-path
Matthias Ronge,

2
Vorrei ricordare che JSONPath non si basa sulla semantica formale di XPath. JSONiq potrebbe essere un'opzione migliore.
wcandillon,

1
@Paramaeleon Funziona benissimo. A proposito, il progetto è stato migrato su GitHub . Mike potrebbe voler aggiungere questo alla risposta, poiché le persone continuano a commentare questo.
Franklin Yu,

21

Penso che JSONQuery sia un superset di JSONPath e quindi lo sostituisce in dojo . Poi c'è anche RQL .

Dalla documentazione del Dojo:

JSONQuery è una versione estesa di JSONPath con funzionalità aggiuntive per la sicurezza, la facilità d'uso e un set completo di strumenti per la query dei dati tra cui filtraggio, ricerca ricorsiva, ordinamento, mappatura, selezione dell'intervallo ed espressioni flessibili con confronti di stringhe di caratteri jolly e vari operatori.

JSONselect ha un altro punto di vista sulla domanda (simile a un selettore CSS, piuttosto che XPath) e ha un'implementazione JavaScript .


4
Il link github JSONQuery sembra essere morto. JSONSelect ora ha anche una versione JavaScript.
Henrik Aasted Sørensen,

19

Altre alternative di cui sono a conoscenza sono

  1. Specifica JSONiq , che specifica due sottotipi di linguaggi: uno che nasconde i dettagli XML e fornisce una sintassi simile a JS, e uno che arricchisce la sintassi XQuery con costruttori JSON e simili. Zorba implementa JSONiq.
  2. Corona , che si basa su MarkLogic, fornisce un'interfaccia REST per l'archiviazione, la gestione e la ricerca di contenuti XML, JSON, di testo e binari.
  3. MarkLogic 6 e versioni successive forniscono un'interfaccia REST simile a Corona pronta all'uso .
  4. MarkLogic 8 e versioni successive supportano JSON in modo nativo sia nel loro ambiente JavaScript XQuery che sul lato server. È possibile applicare XPath su di esso.

HTH.


3
Ora esiste un'implementazione JSONiq: Zorba 2.6 la supporta ufficialmente.
Ghislain Fourny,

Nota: MarkLogic memorizza JSON in modo nativo a partire dalla versione 8 e consente di applicare XPath direttamente su di esso.
grtjn,

18

Per riassumere alcune delle opzioni correnti per attraversare / filtrare i dati JSON e fornire alcuni esempi di sintassi ...

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

  • json: select () (ispirato maggiormente ai selettori CSS)
    .automobiles .maker:val("Honda") .model

  • JSONPath (ispirato più da XPath)
    $.automobiles[?(@.maker='Honda')].model

Penso che JSPath sia il più bello, quindi cercherò di integrarlo con la mia app AngularJS + CakePHP.

(Inizialmente avevo pubblicato questa risposta in un'altra discussione, ma ho pensato che sarebbe stata utile anche qui.)


Ottimo riassunto ed esempi, anche a causa della menzione dell'ispirazione trovata nei selettori CSS o XPath.
Jochem Schulenklopper,

13

Prova a usare JSPath

JSPath è un linguaggio specifico del dominio (DSL) che consente di navigare e trovare dati all'interno dei documenti JSON. Utilizzando JSPath, è possibile selezionare elementi di JSON per recuperare i dati in essi contenuti.

JSPath per JSON come un XPath per XML.

È fortemente ottimizzato sia per Node.js che per i browser moderni.


9

XQuery può essere utilizzato per eseguire query su JSON, a condizione che il processore offra il supporto JSON. Questo è un semplice esempio di come BaseX può essere usato per trovare oggetti con "id" = 1:

json:parse('[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [ "etc." ] }
    ]}
]')//value[.//id = 1]

(6 anni dopo) Saxon eseguirà XQuery 3.1, che interroga JSON. La mia esperienza con Saxon sta usando il file jar gestito da Java. Esiste un modulo nodo chiamato saxon-java ma non sono sicuro di come funzioni con json. E c'è un'altra cosa nuova di Saxonica chiamata Saxon-JS.
charles ross

9

Esiste una specie di linguaggio di query ...

JQ definisce un J SON q lingua uery che è molto simile a JSONPath - vedi https://github.com/stedolan/jq/wiki/For-JSONPath-users

... [quale] posso usare per trovare un oggetto in [0] .object dove id = 3?

Presumo che ciò significhi: trova tutti gli oggetti JSON nella chiave specificata con id == 3, indipendentemente da dove si trovi l'oggetto. Una query jq corrispondente sarebbe:

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

dove "|" è l'operatore pipe (come nei pipe di comando shell) e dove il segmento ".. | oggetti" corrisponde a "indipendentemente da dove si trovi l'oggetto".

Le basi di jq sono in gran parte ovvie o intuitive o almeno abbastanza semplici, e la maggior parte del resto è facile da imparare se hai familiarità con le pipe della shell dei comandi. Le FAQ di jq hanno indicazioni per tutorial e simili.

jq è anche come SQL in quanto supporta le operazioni CRUD, sebbene il processore jq non sovrascriva mai il suo input. jq può anche gestire flussi di entità JSON.

Altri due criteri che potresti prendere in considerazione nella valutazione di un linguaggio di query orientato a JSON sono:

  • supporta le espressioni regolari? (jq 1.5 ha un supporto completo per regex PCRE)
  • è Turing-completo? (Sì)

8

Defiant.js sembra anche piuttosto interessante, ecco un semplice esempio:

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

Purtroppo, al momento non pubblicato su npm e richiede installazione manuale ...
Andrew Mao,


7

Jsel è fantastico e si basa su un vero motore XPath. Ti consente di creare espressioni XPath per trovare qualsiasi tipo di dati JavaScript, non solo oggetti (anche stringhe).

Puoi creare schemi e mappature personalizzati per darti il ​​controllo completo su come i tuoi dati sono calpestabili dal motore XPath. Uno schema è un modo per definire come elementi, elementi secondari, attributi e valori dei nodi sono definiti nei dati. Quindi puoi creare le tue espressioni per adattarle.

Dato che avevi una variabile chiamata datache conteneva JSON dalla domanda, puoi usare jsel per scrivere:

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

Ciò restituirà qualsiasi nodo con un idattributo di 3. Un attributo è qualsiasi valore primitivo (stringa, numero, data, regex) all'interno di un oggetto.


6

ObjectPath è un linguaggio di query simile a XPath o JSONPath, ma molto più potente grazie ai calcoli aritmetici incorporati, ai meccanismi di confronto e alle funzioni integrate. Vedi la sintassi:

Trova nel negozio tutte le scarpe di colore rosso e prezzo inferiore a 50

$ .. scarpe. * [il colore è "rosso" e prezzo <50]


Mi piace il primo esempio sul sito Web ed è bello che ObjectPath possa essere eseguito in una modalità di shell interattiva, ma quello che sto cercando è usare ObjectPath in uno script Python. Potete indicarmi un esempio che mostra come utilizzare ObjectPath come libreria? Non riesco a trovare nulla del genere sul sito web.
Piokuc,

Si prega di consultare la sezione sull'utilizzo di Python su github . Lo aggiungeremo al sito Web - è davvero difficile da trovare al momento. Se hai bisogno di ulteriore aiuto, puoi pubblicare una domanda sul gruppo di Google .
Ela Bednarek,

Grazie, Ela, gli esempi aggiunti nella pagina di github sono esattamente ciò che era necessario.
Piokuc,


3

JMESPath sembra essere molto popolare in questi giorni (dal 2020) e affronta una serie di problemi con JSONPath. È disponibile per molte lingue.


1

Se sei come me e vuoi solo fare ricerche basate sul percorso, ma non ti importa di XPath reale, lodash _.get()può funzionare. Esempio dai documenti 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'

Sfortunatamente quella funzione può restituire solo un singolo risultato, non supporta il recupero di una matrice di elementi corrispondenti, che è dove brillano le altre librerie.
Simon East,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.