¿Hay un equivalente JSON de XQuery / XPath?

221

Al buscar elementos en matrices y hashes JSON complejos, como:

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

¿Hay algún tipo de lenguaje de consulta que pueda usar para encontrar un artículo in [0].objects where id = 3?

Naftuli Kay
fuente
no a menos que hagas uno. Deje la consulta al servidor y use REST para obtener solo los datos que necesita.
zzzzBov
55
+1 buena idea. Voy a escribir esto mañana ...
2
No es XPath, pero he encontrado que JLinq es bastante bueno (lo que hace que el código se lea como in(...).where(...).select(...)): hugoware.net/Projects/jLinq .
pimvdb
44
Esto es frustrante porque hay muchas bibliotecas, pero nada se acerca a un estándar comúnmente aceptado. Tenemos una biblioteca utilizada por terceros, por lo que debemos proporcionar un lenguaje de consulta que sea ampliamente conocido y utilizado.
David Thielen
1
Claro, puede usar jsel - github.com/dragonworx/jsel - dado que tiene una variable dataque contiene su objeto JSON, escribiría: jsel(data).select("//*[@id=3]")y devolvería el objeto que contiene la clave de identificación con 3.
Ali

Respuestas:

122

Sí, se llama JSONPath . La fuente ahora está en GitHub .

También está integrado en DOJO .

Mike Christensen
fuente
3
La respuesta de Brian sugiere que el módulo jsonQuery debería usarse en lugar del módulo jsonPath en dojo.
hugomg
55
¿Qué tan sólido es esto? Y no puedo encontrar una versión de Java o C # que sea un factor decisivo para nosotros.
David Thielen
2
El sitio vinculado aquí proporciona Javascript y PHP. Si necesita una implementación de Java, hay una aquí: code.google.com/p/json-path
Matthias Ronge
2
Debo mencionar que JSONPath no se basa en la semántica formal XPath. JSONiq podría ser una mejor opción.
wcandillon
1
@Paramaeleon Eso funciona muy bien. El proyecto ha sido migrado a GitHub , por cierto. Mike puede querer agregar esto a la respuesta, ya que la gente sigue comentando sobre esto.
Franklin Yu
21

Creo que JSONQuery es un superconjunto de JSONPath y, por lo tanto, lo reemplaza en dojo . Luego también está RQL .

De la documentación del Dojo:

JSONQuery es una versión extendida de JSONPath con características adicionales para seguridad, facilidad de uso y un conjunto integral de herramientas de consulta de datos que incluyen filtrado, búsqueda recursiva, clasificación, mapeo, selección de rango y expresiones flexibles con comparaciones de cadenas comodín y varios operadores.

JSONselect tiene otro punto de vista sobre la pregunta (como un selector CSS, en lugar de XPath) y tiene una implementación de JavaScript .

Brian Clozel
fuente
44
El enlace github JSONQuery parece estar muerto. JSONSelect también tiene una versión de JavaScript ahora.
Henrik Aasted Sørensen
19

Otras alternativas que conozco son

  1. Especificación JSONiq , que especifica dos subtipos de lenguajes: uno que oculta detalles XML y proporciona una sintaxis similar a JS, y otro que enriquece la sintaxis XQuery con constructores JSON y demás. Zorba implementa JSONiq.
  2. Corona , que se basa en MarkLogic, proporciona una interfaz REST para almacenar, administrar y buscar contenido XML, JSON, de texto y binario.
  3. MarkLogic 6 y versiones posteriores proporcionan una interfaz REST similar a la de Corona.
  4. MarkLogic 8 y versiones posteriores admiten JSON de forma nativa tanto en su entorno XQuery como en JavaScript del lado del servidor. Puede aplicar XPath en él.

HTH

grtjn
fuente
3
Ahora hay una implementación JSONiq: Zorba 2.6 lo admite oficialmente.
Ghislain Fourny
Nota: MarkLogic almacena JSON de forma nativa a partir de la versión 8 y permite aplicar XPath directamente.
grtjn
18

Para resumir algunas de las opciones actuales para atravesar / filtrar datos JSON, y proporcionar algunos ejemplos de sintaxis ...

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

  • json: select () (inspirado más en selectores CSS)
    .automobiles .maker:val("Honda") .model

  • JSONPath (inspirado más en XPath)
    $.automobiles[?(@.maker='Honda')].model

Creo que JSPath se ve mejor, así que intentaré integrarlo con mi aplicación AngularJS + CakePHP.

(Originalmente publiqué esta respuesta en otro hilo, pero pensé que sería útil aquí también).

Simon East
fuente
Gran resumen y ejemplos, también por mencionar la inspiración que se encuentra en los selectores CSS o XPath.
Jochem Schulenklopper
13

Intenta usar JSPath

JSPath es un lenguaje específico de dominio (DSL) que le permite navegar y encontrar datos dentro de sus documentos JSON. Con JSPath, puede seleccionar elementos de JSON para recuperar los datos que contienen.

JSPath para JSON como un XPath para XML.

Está muy optimizado tanto para Node.js como para los navegadores modernos.

dfilatov
fuente
9

XQuery se puede utilizar para consultar JSON, siempre que el procesador ofrezca compatibilidad con JSON. Este es un ejemplo sencillo de cómo BaseX se puede utilizar para buscar objetos con "id" = 1:

json:parse('[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [ "etc." ] }
    ]}
]')//value[.//id = 1]
Christian Grün
fuente
(6 años después) Saxon ejecutará XQuery 3.1, que consulta JSON. Mi experiencia sajona está utilizando el archivo jar ejecutado por java. Hay un módulo de nodo llamado saxon-java pero no estoy seguro de cómo funciona eso con json. Y hay otra cosa nueva de Saxonica llamada Saxon-JS.
charles ross
9

¿Hay algún tipo de lenguaje de consulta ...

jq define un lenguaje de consulta J SON q que es muy similar a JSONPath; consulte https://github.com/stedolan/jq/wiki/For-JSONPath-users

... [que] puedo usar para encontrar un elemento en [0] .objects donde id = 3?

Asumiré que esto significa: encuentre todos los objetos JSON bajo la clave especificada con id == 3, sin importar dónde pueda estar el objeto. Una consulta jq correspondiente sería:

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

donde "|" es el operador de tubería (como en las tuberías de shell de comando), y donde el segmento ".. | objetos" corresponde a "sin importar dónde pueda estar el objeto".

Los conceptos básicos de jq son en gran medida obvios o intuitivos o al menos bastante simples, y la mayoría del resto es fácil de aprender si está familiarizado con las tuberías de shell de comandos. Las preguntas frecuentes de jq tienen punteros a tutoriales y similares.

jq también es como SQL porque admite operaciones CRUD, aunque el procesador jq nunca sobrescribe su entrada. jq también puede manejar flujos de entidades JSON.

Otros dos criterios que puede considerar al evaluar un lenguaje de consulta orientado a JSON son:

  • ¿admite expresiones regulares? (jq 1.5 tiene soporte completo para PCRE regex)
  • ¿Es Turing completo? (Sí)
pico
fuente
8

Defiant.js también se ve muy bien, aquí hay un ejemplo 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
fuente
Desafortunadamente, no publicado en npm en este momento y requiere instalación manual ...
Andrew Mao
7

Jsel es impresionante y se basa en un verdadero motor XPath. Le permite crear expresiones XPath para encontrar cualquier tipo de datos de JavaScript, no solo objetos (cadenas también).

Puede crear esquemas y mapeos personalizados para darle un control completo sobre cómo sus datos son transitables por el motor XPath. Un esquema es una forma de definir cómo los elementos, elementos secundarios, atributos y valores de nodo se definen en sus datos. Luego puedes crear tus propias expresiones para adaptarlas.

Dado que tenía una variable llamada dataque contenía el JSON de la pregunta, podría usar jsel para escribir:

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

Esto devolverá cualquier nodo con un idatributo de 3. Un atributo es cualquier valor primitivo (cadena, número, fecha, expresión regular) dentro de un objeto.

Ali
fuente
6

ObjectPath es un lenguaje de consulta similar a XPath o JSONPath, pero mucho más potente gracias a los cálculos aritméticos integrados, los mecanismos de comparación y las funciones integradas. Ver la sintaxis:

Encuentra en la tienda todos los zapatos de color rojo y precio inferior a 50

$ .. zapatos. * [el color es "rojo" y el precio <50]

Ela Bednarek
fuente
Me gusta el primer ejemplo en el sitio web y es genial que ObjectPath pueda ejecutarse en un modo interactivo, similar a un shell, pero lo que estoy buscando es usar ObjectPath en un script de Python. ¿Me puede señalar un ejemplo que muestre cómo usar ObjectPath como biblioteca? No puedo encontrar algo así en el sitio web.
piokuc
Consulte la sección sobre el uso de Python en github . Agregaremos esto al sitio web; de hecho, es difícil de encontrar en este momento. Si necesita más ayuda, puede publicar una pregunta en el grupo de Google .
Ela Bednarek
Gracias, Ela, los ejemplos agregados en la página de Github son exactamente lo que se necesitaba.
piokuc
4

@Naftule: con "defiant.js", es posible consultar una estructura JSON con expresiones XPath. Echa un vistazo a este evaluador para tener una idea de cómo funciona:

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

A diferencia de JSONPath, "defiant.js" ofrece el soporte a gran escala de la sintaxis de consulta, de XPath en estructuras JSON.

El código fuente de defiant.js se puede encontrar aquí:
https://github.com/hbi99/defiant.js

Hakan Bilgin
fuente
3

JMESPath parece ser muy popular en estos días (a partir de 2020) y aborda una serie de problemas con JSONPath. Está disponible para muchos idiomas.

jlh
fuente
1

Si eres como yo y solo quieres hacer búsquedas basadas en rutas, pero no te importa el XPath real, lodash _.get()puede funcionar. Ejemplo de lodash docs:

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
fuente
Desafortunadamente, esa función solo puede devolver un único resultado, no admite la obtención de una matriz de elementos coincidentes, que es donde brillan las otras bibliotecas.
Simon East