Guía de consultas JSONPath: Cómo buscar datos JSON
JSON se ha convertido en el lenguaje universal de la Web. Las APIs devuelven JSON, los archivos de configuración usan JSON y las bases de datos almacenan documentos JSON. Pero a medida que las estructuras JSON se vuelven más grandes y más profundamente anidadas, encontrar valores específicos se vuelve cada vez más difícil. Aquí es donde entra JSONPath. JSONPath es un lenguaje de consulta que te permite navegar y extraer datos de documentos JSON usando expresiones de ruta concisas, tal como XPath lo hace para XML. Esta guía cubre todo, desde la sintaxis básica hasta el filtrado avanzado, con ejemplos prácticos que puedes aplicar inmediatamente.
¿Qué es JSONPath?
JSONPath es un lenguaje de consulta JSON propuesto originalmente por Stefan Goessner en 2007. Proporciona una sintaxis compacta para seleccionar nodos de documentos JSON, similar a cómo los selectores CSS apuntan a elementos HTML o las expresiones XPath apuntan a nodos XML. En lugar de escribir bucles y lógica condicional para recorrer estructuras JSON, simplemente escribes una expresión que describe la ruta hacia los datos deseados.
Las expresiones JSONPath comienzan desde el nodo raíz del documento JSON y navegan a través de objetos y arrays hasta el valor deseado. El lenguaje soporta comodines, descenso recursivo, segmentación de arrays y expresiones de filtro, lo suficiente para la mayoría de las necesidades de extracción de datos.
Documento JSON de ejemplo
A lo largo de esta guía, usaremos el siguiente documento JSON como ejemplo de trabajo. Este es el ejemplo clásico de la propuesta original de JSONPath con datos adicionales:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J.R.R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}Referencia de sintaxis JSONPath
JSONPath utiliza un pequeño conjunto de operadores que se combinan para formar consultas potentes. Aquí está la referencia completa de sintaxis:
| Operador | Descripción | Ejemplo |
|---|---|---|
| $ | Nodo raíz del documento | $ |
| . | Operador hijo (accede a propiedades del objeto) | $.store |
| [] | Índice de array u operador hijo | $.store.book[0] |
| [*] | Comodín para todos los elementos del array | $.store.book[*] |
| .. | Descenso recursivo (busca en todos los niveles) | $..author |
| .key | Propiedad de objeto nombrada | $.store.bicycle |
| ['key'] | Notación de corchetes para acceso a propiedades | $['store']['book'] |
| [start:end] | Segmentación de array (índice final no incluido) | $.store.book[0:2] |
| [?()] | Expresiones de filtro | < 10)] |
| () | Expresión de script (depende de la implementación) | $.store.book[(@.length-1)] |
Expresiones básicas de JSONPath
Acceso al nodo raíz y a los hijos directos
El signo de dólar $ representa el nodo raíz del documento JSON. Desde allí, usas la notación de punto para acceder a las propiedades del objeto y la notación de corchetes para acceder a los índices del array.
| Expresión | Resultado |
|---|---|
| $ | Todo el documento JSON |
| $.store | El objeto store (contiene el array book y el objeto bicycle) |
| $.store.bicycle | {"color": "red", "price": 19.95} |
| $.store.bicycle.color | "red" |
| $.store.book | Todo el array book |
| $.store.book[0] | El primer objeto book |
| $.store.book[0].title | "Sayings of the Century" |
| $.store.book[3].author | "J.R.R. Tolkien" |
Notación de corchetes
La notación de corchetes es una alternativa a la notación de punto, útil cuando los nombres de propiedad contienen caracteres especiales, espacios o comienzan con un número:
$.store['book'][0]['title']
$['store']['bicycle']['color']La notación de corchetes y la notación de punto son intercambiables para las propiedades del objeto. Sin embargo, la notación de corchetes es obligatoria cuando los nombres de propiedad son dinámicos o contienen caracteres que no son válidos en la notación de punto.
Operador comodín
El operador comodín * coincide con todos los elementos de un array o todas las propiedades de un objeto. Es extremadamente útil para extraer todos los valores en un nivel sin conocer las claves o índices específicos.
| Expresión | Resultado |
|---|---|
| $.store.* | Todos los valores del objeto store (el array book y el objeto bicycle) |
| $.store.book[*] | Todos los libros del array (los cuatro objetos book) |
| $.store.book[*].author | Todos los nombres de autor: ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"] |
| $.store.*.price | El precio de bicycle y el array book (no los precios de los libros individuales) |
Descenso recursivo: el operador de doble punto
El operador de doble punto .. es una de las características más potentes de JSONPath. Busca la clave especificada en cada nivel del árbol JSON, no solo en los hijos directos. Piensa en ello como una búsqueda profunda en todo el documento.
| Expresión | Resultado |
|---|---|
| $..author | Valores de author en todas las ubicaciones del documento |
| $..price | Todos los valores de price: [8.95, 12.99, 8.99, 22.99, 19.95] |
| $..book[2] | El tercer libro, encontrado recursivamente |
| $..category | Todos los valores de category: ["reference", "fiction", "fiction", "fiction"] |
El operador de descenso recursivo es particularmente útil cuando no conoces la ruta exacta hacia los datos deseados, o cuando la misma clave aparece en múltiples niveles de anidamiento. Por ejemplo, si una respuesta de API contiene campos id en varios niveles de anidamiento, $..id recopilaría todos los id.
Segmentación de arrays
La segmentación de arrays te permite seleccionar un rango de elementos de un array. La sintaxis [start:end] selecciona elementos desde el índice de inicio hasta (pero sin incluir) el índice final. Se soportan índices positivos y negativos.
| Expresión | Resultado |
|---|---|
| $.store.book[0:2] | Los dos primeros libros (índices 0 y 1) |
| $.store.book[1:3] | El segundo y tercer libro (índices 1 y 2) |
| $.store.book[-1] | El último libro (The Lord of the Rings) |
| $.store.book[-2:] | Los dos últimos libros |
| $.store.book[:2] | Los dos primeros libros (igual que [0:2]) |
| $.store.book[2:] | El tercer libro y siguientes |
Ten en cuenta que el comportamiento de segmentación puede variar ligeramente entre diferentes implementaciones de JSONPath. La sintaxis anterior sigue las convenciones utilizadas por la mayoría de las bibliotecas populares y el estándar IETF RFC 9535.
Expresiones de filtro
Las expresiones de filtro son donde JSONPath se vuelve realmente potente. Te permiten seleccionar elementos basados en condiciones en lugar de posición. La sintaxis de filtro usa [?(condition)], donde la condición se evalúa para cada elemento.
Operadores de comparación
JSONPath soporta los siguientes operadores de comparación en expresiones de filtro:
| Operador | Significado | Ejemplo |
|---|---|---|
| == | Igual a | [?(@.category == "fiction")] |
| != | No igual a | [?(@.category != "fiction")] |
| < | Menor que | < 10)] |
| <= | Menor o igual que | <= 8.99)] |
| > | Mayor que | [?(@.price > 15)] |
| >= | Mayor o igual que | [?(@.price >= 12.99)] |
| =~ | Coincidencia de regex (implementación parcial) | [?(@.author =~ /Tolkien/i)] |
Ejemplos prácticos de filtrado
Usando nuestro documento de ejemplo, aquí hay expresiones de filtro prácticas y sus resultados:
Find all books cheaper than $10:
< 10)]Devuelve los libros "Sayings of the Century" ($8.95) y "Moby Dick" ($8.99).
Find all fiction books:
$.store.book[?(@.category == "fiction")]Devuelve tres libros: "Sword of Honour", "Moby Dick" y "The Lord of the Rings".
Find books with an ISBN:
$.store.book[?(@.isbn)]Devuelve los libros que tienen una propiedad isbn: "Moby Dick" y "The Lord of the Rings". Esto se debe a que el filtro verifica la existencia de la propiedad.
Find the most expensive book:
$.store.book[?(@.price > 20)]Devuelve "The Lord of the Rings" ($22.99).
Operadores lógicos en filtros
Puedes combinar condiciones usando operadores lógicos:
< 10 && @.category == "fiction")]
$.store.book[?(@.price > 15 || @.category == "reference")]La primera expresión encuentra libros de ficción por debajo de $10 (solo "Moby Dick"). La segunda encuentra libros que cuestan más de $15 o pertenecen a la categoría de referencia (devuelve "Sayings of the Century" y "The Lord of the Rings").
JSONPath vs. XPath
JSONPath está explícitamente modelado según XPath, y los dos lenguajes comparten muchas similitudes conceptuales. Si estás familiarizado con el procesamiento XML, comprender esta relación es útil.
| Funcionalidad | JSONPath | XPath |
|---|---|---|
| Símbolo raíz | $ | / |
| Acceso a hijos | .key o ['key'] | /element |
| Índice de array | [0] | [1] (comienza en 1) |
| Comodín | * | * |
| Recursión de niveles: especifica la profundidad máxima de anidamiento permitida para objetos y arrays. | .. | // |
| Validación condicional: aplica diferentes reglas de validación basadas en el valor de otro campo. | [?(condition)] | [condition] |
| Propiedad | Formato de fecha y hora: valida cadenas de fecha y hora ISO 8601 con restricciones de zona horaria. | @attr |
| Campos opcionales: marca campos como opcionales eliminándolos de la lista required. | Valores predeterminados: especifica valores predeterminados que se aplican cuando un campo está ausente. | ¿Existen herramientas que generen código a partir de JSON Schema? |
| Sí, varias herramientas pueden generar código a partir de JSON Schema: quicktype genera TypeScript, Go, C# y otros tipos de lenguaje; json-schema-to-typescript crea interfaces TypeScript; datamodel-code-generator genera modelos Python; jsonschema2pojo genera clases Java. Estas herramientas aceleran el desarrollo asegurando que los tipos de código coincidan con tu Schema. | Si/no/entonces: especifica condiciones que determinan qué Schema validar. | .. |
| Si la propiedad de condición contiene un valor específico, valida contra el Schema "then". | Si/no/entonces: especifica condiciones que determinan qué Schema validar. | Si la propiedad de condición contiene un valor diferente, valida contra el Schema "else". |
| Si ninguna condición coincide, o si no hay cláusula "else", la validación pasa por defecto. | El Schema en "then" se aplica cuando el valor de paymentMethod es "credit_card". | El Schema en "else" se aplica cuando el valor de paymentMethod es "paypal". |
La diferencia clave es que XPath opera sobre un modelo de árbol rico con elementos, atributos, nodos de texto, espacios de nombres e instrucciones de procesamiento. JSONPath opera sobre un modelo más simple de objetos (mapas clave-valor) y arrays (listas ordenadas). Esta simplicidad hace que JSONPath sea más fácil de aprender pero menos expresivo que XPath para consultas complejas.
JSONPath en la práctica
Pruebas de API
JSONPath es indispensable para las pruebas de API. Cuando envías una solicitud a una API y recibes una respuesta JSON grande, JSONPath te permite hacer afirmaciones sobre valores específicos sin navegar manualmente toda la estructura. La mayoría de las herramientas de prueba de API soportan JSONPath de forma nativa.
Por ejemplo, en una prueba podrías verificar que el primer libro cuesta menos de $10:
// Using a JSONPath assertion in testing
response.jsonPath().get("store.book[0].price").should(equals(8.95));
// Find all books by a specific author
response.jsonPath().get("store.book[?(@.author == 'Herman Melville')].title");
// Returns: ["Moby Dick"]Transformación de datos
Al integrar sistemas que usan diferentes formatos de datos, JSONPath ayuda a extraer y transformar campos específicos. Puedes extraer valores de una estructura JSON y mapearlos a otra sin escribir código de recorrido complejo.
Gestión de configuración
Los archivos de configuración complejos a menudo contienen JSON profundamente anidado. JSONPath te permite consultar valores de configuración específicos sin cargar y analizar toda la estructura. Herramientas como jq usan una sintaxis similar a JSONPath para procesar JSON en tuberías de línea de comandos.
Monitorización y alertas
En sistemas de observabilidad, las consultas JSONPath pueden extraer métricas de logs y respuestas de API en formato JSON. Puedes configurar alertas que se activen cuando una consulta JSONPath devuelva valores que excedan un umbral.
Implementaciones de JSONPath
JSONPath está disponible en prácticamente todos los lenguajes de programación. Aquí están las bibliotecas más populares:
| Lenguaje | Biblioteca | Instalación |
|---|---|---|
| JavaScript | jsonpath-plus | npm install jsonpath-plus |
| Python | jsonpath-ng | pip install jsonpath-ng |
| Java | JsonPath (Jayway) | Maven: com.jayway.jsonpath |
| C# | Json.NET (Newtonsoft) | NuGet: Newtonsoft.Json |
| Go | gjson | go get github.com/tidwall/gjson |
| PHP | jsonpath | composer require softcreatr/jsonpath |
| Ruby | jsonpath | gem install jsonpath |
Ejemplo en JavaScript
< 10)]',
json: data
});
// Returns books with price < 10
Python Example
from jsonpath_ng import parse
data = { /* our sample JSON */ }
# Find all authors
author_expr = parse('$..author')
authors = [match.value for match in author_expr.find(data)]
# ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
# Find cheap books
cheap_expr = parse('$.store.book[?(@.price < 10)]')
cheap_books = [match.value for match in cheap_expr.find(data)]
Common Pitfalls and Tips
- Zero-based vs one-based indexing: JSONPath uses zero-based indexing (the first element is [0]), while XPath uses one-based indexing (the first element is [1]). This is a common source of off-by-one errors.
- Implementation differences: Before the IETF standard (RFC 9535), JSONPath implementations varied in their handling of edge cases like empty results, null values, and filter syntax. Always test your expressions with the specific library you are using.
- Filter performance: Recursive descent with filters (
$..book[?(@.price < 10)]) can be slow on large documents because it must traverse the entire tree. For performance-critical applications, use more specific paths when possible. - Case sensitivity: JSONPath is case-sensitive.
$.Storewill not match$.store. This is consistent with JSON's case-sensitive nature. - Indexación basada en cero vs. basada en uno: JSONPath usa indexación basada en cero (el primer elemento es [0]), mientras que XPath usa indexación basada en uno (el primer elemento es [1]). Esta es una fuente común de errores por uno.
- Diferencias de implementación: antes del estándar IETF (RFC 9535), las implementaciones de JSONPath variaban en el manejo de casos límite como resultados vacíos, valores null y sintaxis de filtro. Siempre prueba las expresiones con tu biblioteca específica.
Trampas comunes y consejos
En 2024, el IETF publicó el RFC 9535, estandarizando formalmente JSONPath. La especificación resuelve muchas de las ambigüedades e inconsistencias que existían entre implementaciones. Los aspectos clave del estándar incluyen:
- < 10)]) puede ser lento en documentos grandes porque debe recorrer todo el árbol. Para aplicaciones críticas de rendimiento, usa rutas más específicas cuando sea posible.
- Sensibilidad a mayúsculas: JSONPath distingue entre mayúsculas y minúsculas. $.Store no coincidirá con $.store. Esto es consistente con la naturaleza de JSON de distinguir mayúsculas y minúsculas.
- Escape de caracteres especiales: si los nombres de clave contienen puntos o corchetes, debes usar la notación de corchetes con comillas: $['key.with.dots'] en lugar de $.key.with.dots.
- Sin recorrido hacia el padre: a diferencia de XPath, JSONPath no puede navegar al nodo padre. No hay equivalente al .. (eje padre) de XPath. El .. de JSONPath significa descenso recursivo, no padre.
Si estás comenzando un nuevo proyecto, prefiere bibliotecas que implementen el RFC 9535 para máxima compatibilidad y comportamiento predecible.
¿Necesitas consultar datos JSON rápidamente? Prueba nuestro probador de JSONPath en línea gratuito para evaluar expresiones contra tus documentos JSON en tiempo real.
Si paymentMethod no es ni "credit_card" ni "paypal", ninguna condición se aplica y la validación pasa por defecto.Estándar IETF: RFC 9535
Ejemplo en Python
JSONPath es un lenguaje de consulta JSON, similar a XPath para XML. Utiliza expresiones de ruta para navegar y extraer valores específicos de documentos JSON. Una expresión JSONPath como $.store.book[0].title te permite localizar datos con precisión en estructuras JSON complejas y anidadas sin escribir código de análisis personalizado.
¿Qué es JSONPath?
JSONPath está diseñado para la estructura de objetos y arrays de JSON, mientras que XPath está diseñado para el árbol de elementos y atributos de XML. JSONPath usa $ como nodo raíz, notación de punto para acceder a objetos y notación de corchetes para acceder a arrays. XPath usa / para separación de rutas y @ para acceder a atributos. JSONPath es más simple pero menos rico en funcionalidades que XPath.
¿En qué se diferencia JSONPath de XPath?
El doble punto (..) en JSONPath es el operador de descenso recursivo. Busca la clave nombrada en todos los niveles de la estructura JSON, no solo en los hijos directos. Por ejemplo, $..author encuentra todas las claves author en cualquier lugar de todo el documento, sin importar cuán profundamente estén anidadas.
¿Qué significa el doble punto (..) en JSONPath?
<, ><=, >< 10)] encuentra todos los libros que cuestan menos de $10.
¿Puede JSONPath filtrar datos según condiciones?
JSONPath fue propuesto originalmente por Stefan Goessner en 2007 sin una especificación formal, lo que llevó a variaciones entre implementaciones. En 2024, el IETF publicó el RFC 9535 estandarizando formalmente JSONPath. Las implementaciones modernas están convergiendo hacia este estándar, pero algunas bibliotecas más antiguas aún pueden tener ligeras diferencias de sintaxis.