JSONPath es un lenguaje de consulta para JSON como XPath lo es para XML: senalas nodos en lugar de escribir bucles anidados. La mayoria de los dias solo necesitas unos tokens - `$`, `@`, puntos, corchetes, `*`, `..`, un slice y un filtro `[?()]` simple. Esta guia es esa lista corta, no un clon completo del RFC. Pega el ejemplo de abajo en el Probador JSONPath y prueba cada expresion en el navegador - no se sube nada.
Respuesta rapida
Empieza cada ruta con `$` (la raiz del documento). Usa `@` dentro de un filtro para el elemento actual. Prefiere `$.store.book[*].title` en el dia a dia; usa `$['store']['book'][0]` cuando la clave tenga espacios o caracteres reservados. `$..author` encuentra un campo a cualquier profundidad. Los filtros se ven como `$.store.book[?(@.price < 10)]`. Trata RFC 9535 como el dialecto moderno y las muestras Goessner antiguas como folklore hasta que las verifiques.
Un mismo payload de ejemplo
Todos los ejemplos usan el documento clasico de la libreria (la misma forma que comparten muchos tutoriales de JSONPath). Mantenlo a mano mientras lees:
- `store.book` - un array de objetos con `category`, `author`, `title`, `price` y a veces `isbn`.
- `store.bicycle` - un objeto anidado con `color` y `price`.
- Si tu payload llego en una sola linea, formatealo primero con el Minificador y formateador JSON y luego consulta.
$ y @
`$` es la raiz del valor JSON que pegaste - el objeto o array completo. Toda expresion util empieza ahi. `@` solo tiene sentido dentro de un filtro: significa "el elemento actual que se esta evaluando". Fuera de un filtro, `@` no es un cursor libre.
- `$` - la raiz del documento.
- `@.price` dentro de `[?()]` - el campo `price` del elemento bajo prueba.
- `$.store.book[?(@.isbn)]` - libros que tienen la clave `isbn` (existencia).
- Una ruta sin `$` suele ser rechazada por testers estrictos - siempre empieza con `$`.
Punto vs corchetes
La notacion con punto es atajo para identificadores simples: `$.store.book`. La notacion con corchetes es la forma explicita: `$['store']['book']`. Usa corchetes cuando la clave no sea un identificador plano (espacios, guiones, digitos al inicio) o cuando quieras el estilo de ruta normalizada RFC 9535 que muchos tools muestran en la tabla de coincidencias.
- `$.store.bicycle.color` - bien para claves ordinarias.
- `$['content-type']` - necesario cuando la clave no es un identificador estilo JS.
- `$['store']['book'][0]['title']` - ruta singular normalizada a un nodo (estilo RFC 9535 §2.7).
- Los indices siempre van entre corchetes: `$.store.book[0]`, no `$.store.book.0`.
* y ..
`*` es un comodin de "cada hijo en este nivel." `..` es descento recursivo: recorre el arbol y recoge coincidencias a cualquier profundidad. Los comodines se quedan en un nivel; el descento puede sorprenderte en documentos grandes.
- `$.store.book[*].title` - el titulo de cada libro (un nivel de items del array).
- `$.store.*` - tanto `book` como `bicycle` bajo `store`.
- `$..author` - cada `author` en cualquier sitio bajo la raiz.
- `$..price` - precios de libros y el del bicycle juntos - estrecha la ruta si solo querias uno.
Slices
Los slices de array usan `start:end:step` estilo Python dentro de corchetes. Los extremos omitidos significan "desde el inicio" o "hasta el final." Los indices negativos cuentan desde el final cuando la implementacion los soporta.
- `$.store.book[0:2]` - los dos primeros libros (indices 0 y 1).
- `$.store.book[-1:]` - el ultimo libro, en motores que permiten indices negativos.
- `$.store.book[::2]` - un libro de cada dos cuando el step esta soportado.
- Los slices seleccionan items del array; encadena un campo despues: `$.store.book[0:2].title`.
Un filtro simple
Los filtros van en `[?(...)]` y conservan los items donde la expresion es verdadera. `@` es el elemento actual. Las comparaciones suelen no coercionar tipos como el JavaScript laxo - `1 == "1"` a menudo es falso. Mantén los filtros aburridos: igualdad, desigualdad, compare numerico, `&&`, `||`, `!` y existencia.
- `$.store.book[?(@.price < 10)]` - libros baratos.
- `$.store.book[?(@.price < 10 && @.category == 'fiction')].title` - filtra y luego extrae un campo.
- `$.store.book[?(@.isbn)]` - items que tienen `isbn`.
- Pon el filtro en el array que estas recorriendo, no en una raiz objeto sola salvo que la raiz sea un array.
RFC 9535 frente al dialecto Goessner antiguo
El articulo de Stefan Goessner de 2007 popularizo JSONPath y muchas librerias siguen copiando sus ejemplos. RFC 9535 (2024) es el estandar IETF: gramatica mas clara, rutas normalizadas y menos escotillas de "eval cualquier cosa". Selectores script como `[(@.length-1)]` y JavaScript libre dentro de filtros pertenecen al viejo oeste, no a un tester seguro en el navegador.
- RFC 9535 - operadores estandarizados, rutas normalizadas como `$['store']['book'][0]`, pensado para implementaciones interoperables.
- Muestras de la era Goessner - siguen en muchos blogs; verificalas antes de usarlas en produccion.
- Subconjuntos sin eval - lo que quieres para payloads de API pegados. Rechaza selectores script; nunca ejecutes la ruta como JavaScript.
- Cuando dos tools discrepan, mira que dialecto reivindican - no cual "se siente" bien.
No es la spec completa
Este articulo es una chuleta de expresiones del dia a dia. Para el detalle normativo, lee RFC 9535. Para pruebas privadas contra tu propio JSON, usa el Probador JSONPath.
Cinco ejemplos para copiar y pegar
Sobre el sample de la libreria, prueba estos en orden:
- `$.store.book[*].title` - todos los titulos como lista.
- `$..author` - cada autor via descento recursivo.
- `$.store.book[0:2]` - los dos primeros objetos libro.
- `$.store.book[?(@.price < 10)]` - libros con precio menor que 10.
- `$.store.book[?(@.price < 10)].title` - el mismo filtro, solo titulos.
Cuando hayas extraido una lista plana de registros, quizas quieras verla en hoja de calculo - pasa un array JSON de objetos por el Conversor JSON a CSV. Para blobs de API anidados que aun exploras, quedate en JSONPath hasta que la forma este clara.
Preguntas frecuentes
Toda ruta JSONPath empieza con $?
Si en la practica. `$` nombra la raiz. Las tools estrictas rechazan rutas que lo omiten.
Cuando uso @?
Solo dentro de filtros `[?()]`, como el elemento actual. No sustituye a `$` al inicio de una ruta.
Por que obtuve cero coincidencias?
Una ruta valida puede no coincidir con nada. Causas frecuentes: filtrar una raiz objeto en lugar de un array, un typo en una clave, o esperar coercion de tipos de JavaScript. Prueba `$..field` para confirmar que el campo existe y luego estrecha.
JSONPath es lo mismo que JMESPath o jq?
No. Idea emparentada, sintaxis y librerias distintas. Elige un dialecto por codebase y mantente en el.
Puedo probar una respuesta de API privada con seguridad?
Si si el evaluador corre en tu navegador sin subir nada. El Probador JSONPath esta hecho para eso - pega, consulta, copia JSON extraido o rutas normalizadas.
Pruebalo en ToolsMinify
Todas las tools de abajo corren en tu navegador - gratis, sin registro, sin subidas:
- Probador JSONPath - pega JSON, ejecuta una expresion, copia coincidencias o valores extraidos.
- Minificador y formateador JSON - formatea o minifica un payload antes de consultarlo.
- Conversor JSON a CSV - convierte un array JSON plano de objetos a CSV despues de extraerlo.
- Todas las herramientas de desarrollo - el indice completo de la categoria.
Pruebalo gratis
Abre el Probador JSONPath, carga el sample de la libreria y pega `$.store.book[?(@.price < 10)].title`. Deberias ver los titulos baratos - todo en tu dispositivo.