Filtrar JSON
Extrae solo lo que necesitas con una expresión de filtro JSONPath.
Nada de lo que pegues sale de tu navegador. La lista de permitidos de connect-src convierte eso en una garantía del navegador, no en una promesa. Compruébalo tú mismo
Reduce un documento grande a la parte que necesitas, usando una expresión de filtro JSONPath. El resultado vuelve como un array JSON con los valores que encajan, listo para copiar.
Para que quede claro qué es esto: es JSONPath, no jq. jq es un lenguaje completo y una herramienta genuinamente mejor para transformaciones complejas. Esto es para seleccionar, que es lo que la mayoría de los filtros son en realidad.
Expresiones de filtro
Toda la sintaxis en un solo sitio, porque esta es la parte que la gente consulta cada vez.
- $.items[?@.active]
- Todos los elementos donde la clave existe y es verdadera. La mera existencia ya es una prueba válida.
- $.items[?@.price < 10]
- Comparación numérica. El orden solo se aplica entre dos números o entre dos cadenas.
- $.items[?@.type == 'book']
- Comparación de cadenas. El literal debe ir entrecomillado, y ese es el error más frecuente.
- $.items[?@.price < 10 && @.stock > 0]
- Conjunción con && y disyunción con ||, y agrupación con paréntesis.
- $.items[?!@.archived]
- Negación, que aquí significa que la clave falta o es falsa.
- $.items[?length(@.tags) > 2]
- Una extensión de función. length() funciona sobre cadenas, arrays y objetos.
- $.items[?match(@.sku, '[A-Z]{3}-[0-9]+')]
- Una expresión regular anclada al valor completo. Usa search() para una coincidencia parcial.
- $..[?@.id == 42]
- Un filtro aplicado a cualquier profundidad, que es como encuentras un registro sin saber dónde vive.
Qué pasa con una clave ausente
Aquí es donde más discrepaban las implementaciones anteriores a la RFC, así que conviene decirlo. En la RFC 9535, una consulta que no selecciona nada es «ausente», y un valor ausente solo es igual a otro valor ausente. Así que @.price < 10 es falso cuando price no está, en vez de lanzar un error o encajar. Para que una comparación con == sea verdadera, ambas partes deben estar ausentes.
La consecuencia práctica: para comprobar la ausencia usa !@.price y no @.price == null, porque null es un valor y la ausencia no lo es.
How to do this in code
Filtrar en código, donde jq suele ser la respuesta correcta.
sh jq
El tercer ejemplo es la línea que lo decide: si necesitas agrupar o agregar, usa jq.
# Select, then reshape
jq '[.items[] | select(.price < 10) | {sku, price}]' data.json
# Filter at any depth
jq '[.. | objects | select(.id? == 42)]' data.json
# Group and aggregate, which JSONPath cannot do at all
jq 'group_by(.category) | map({category: .[0].category, n: length})' data.json py Python
# A comprehension beats a query language for anything you
# can express directly.
cheap = [i for i in data['items'] if i['price'] < 10]
# JMESPath when the filter is configuration rather than code
import jmespath
cheap = jmespath.search("items[?price < `10`]", data) js JavaScript
const cheap = data.items.filter((i) => i.price < 10);
// Deep search without a library
function findAll(node, test, out = []) {
if (node && typeof node === 'object') {
if (test(node)) out.push(node);
for (const v of Object.values(node)) findAll(v, test, out);
}
return out;
}
const matches = findAll(data, (n) => n.id === 42); Preguntas frecuentes
- ¿Por qué esto no es un playground de jq?
- Ejecutar jq de verdad en un navegador significa enviarlo compilado a WebAssembly, que ronda el megabyte. En un sitio cuyo argumento es que carga rápido, ese es un mal trato para una herramienta que la mayoría usa para seleccionar y no para transformar. Además, llamar «playground de jq» a un filtro JSONPath sería mentira, y este sitio no hace eso.
- ¿Puedo filtrar y remodelar a la vez?
- Con JSONPath no: selecciona nodos, no construye otros nuevos. Usa JMESPath, que tiene multiselect hashes, o jq.
- ¿Cómo encuentro todos los objetos con una clave dada en cualquier parte del documento?
- $..[?@.laClave] aplica el filtro a cualquier profundidad. Para encontrar un registro concreto, $..[?@.id == 42].