jq Playground · Logs
jq Playground — prueba expresiones jq en línea.
Ni una reimplementación ni un viaje de ida y vuelta a un servidor: el binario real de jq 1.8.2, compilado a WebAssembly y ejecutándose dentro de esta pestaña. Pega tu JSON, escribe el filtro y mira cada salida que jq emite — junto al error exacto que imprimiría si el filtro está mal.
Se ejecuta en tu navegador: nada de lo que pegas sale de esta página. Cómo lo demostramos
jq Playground
-r prints string results without JSON quotes · -s slurps the whole input stream into one array · -n runs the filter once with null as input (read the stream with inputs) · -c prints one line per result instead of pretty-printing.
The version above is read out of the WebAssembly binary at runtime, not written into this page — it is real jq, not a JavaScript re-implementation.
Results update as you type — press Enter to run now.
Press Esc to release keyboard focus from either editor; ⌘/Ctrl + Enter runs and leaves the editor. Nothing you paste is uploaded — jq runs inside this tab.
A jq filter produces a stream of results, not one value: each card below is one output, exactly as jq would print it on its own line. Input is capped at 2 MB, and a filter that never terminates (an unguarded repeat) will freeze this tab until you reload it.
Loading jq — the real binary, compiled to WebAssembly (250–340 KB over the wire, cached after your first visit). The example below runs as soon as it lands.
La brecha
Builtins inventados — y el servidor de otra persona.
Pídele a un asistente una línea de jq y recibirás algo que parece exactamente correcto y falla en la primera ejecución. El fallo favorito es un builtin que no existe: leaf_paths desapareció de jq 1.8.2, así que jq responde leaf_paths/0 is not defined — y la solución, paths(scalars), no es la que te habían dicho. Lo mismo pasa con flags prestados de jaq y gojq, y con afirmaciones muy seguras sobre // que se rompen sin ruido con 0.
La otra opción es un playground que corre en un servidor, que funciona — subiendo el JSON que solo querías inspeccionar. Un intercambio extraño para la salida de kubectl get secret, para una respuesta de API con un token bearer dentro o para una línea de log con el correo de un cliente.
Esta página responde con verdad comprobable. El jq que corre aquí es el programa en C, compilado a WebAssembly, descargado una vez desde este sitio y ejecutado en tu pestaña — y la insignia de versión junto a los flags se lee de ese binario en lugar de teclearse en la página. Cada resultado de builtin de la tabla de referencia de abajo salió del mismo binario y está fijado por un test, así que esta página no puede alejarse de lo que jq hace de verdad.
¿Trabajas con logs y no con JSON? El probador de regex para logs hace lo mismo con las líneas sin estructura.
El proceso
Cómo funciona.
Cuatro pasos, todos dentro de la pestaña de tu navegador — y el tercero es el binario real de jq, no una imitación.
-
Descargar el binario real, una vez.
jq 1.8.2 como WebAssembly — 907 KB sin comprimir, entre 250 y 340 KB por la red según la codificación que negocie tu navegador — servido desde este sitio como archivo estático con hash en el nombre y guardado en la caché de tu navegador. Se carga mientras lees, no mientras esperas.
-
Compilar el filtro.
jq compila tu programa antes de ver ninguna entrada. Un error de sintaxis o una función no definida terminan con código 3 — y obtienes el mensaje propio de jq con su línea, su columna y su fragmento con el caret, no un «expresión no válida».
-
Ejecutarlo sobre tu entrada.
Tu JSON llega a jq por stdin, solo con los flags que muestra la fila de flags. jq emite un flujo de resultados, y cada uno pasa a ser su propia tarjeta — porque un flujo de cuatro valores no es la misma respuesta que un array de cuatro.
-
Clasificar lo que vuelve.
jq usa el código de salida 5 para dos cosas: un error de ejecución y una entrada que no se puede parsear. Aquí se distinguen por el prefijo de stderr y se señalan en el editor al que pertenecen. Las salidas producidas antes del fallo se conservan, y todo lo que jq escribió en stderr se muestra incluso cuando terminó con 0.
Con un ejemplo
jq puede fallar dos veces y aun así devolver 0.
El código de salida de jq refleja solo la ÚLTIMA entrada que procesó. Dale un flujo en el que dos valores rompan el filtro y el último no, y un paso de CI que comprueba $? verá una ejecución limpia.
Cinco entradas, dos de ellas mal
Un flujo de cinco valores JSON y el filtro .+1. Las cadenas no se pueden sumar a números, así que dos de las cinco fallan.
1 "x" 2 "y" 3 Tres resultados, dos errores, salida 0
El playground muestra las tres salidas Y las dos líneas de stderr, y explica por qué el código de salida es 0 — mueve la cadena al final del flujo y el mismo filtro termina con 5.
3 outputs · 3 ms · 2 stderr lines
output 1 2
output 2 3
output 3 4
jq also wrote to stderr 2 lines
string ("x") and number (1) cannot be added
string ("y") and number (1) cannot be added Pruébalo arriba: el panel de resultados lista las dos líneas de stderr bajo «jq also wrote to stderr», con el código de salida al lado. No se esconde nada solo porque jq considere que la ejecución fue un éxito.
Referencia
Los builtins de jq que de verdad usas.
26 filtros, cada uno con una entrada real y la salida exacta que jq 1.8.2 produjo para ella. Teclea el filtro de cualquier fila en el playground de arriba y míralo correr sobre tus propios datos.
| Filtro | Entrada | Salida — jq 1.8.2 |
|---|---|---|
| .a.b | {"a":{"b":42}} | 42 Acceso por ruta. Una clave que falta es null, no un error — indexar algo que no es un objeto sí lo es: .a sobre [1,2] falla con «Cannot index array with string». |
| .items[] | .name | {"items":[{"name":"web"},{"name":"api"}]} | "web" "api" DOS salidas, no un array. Envuelve todo el filtro en [ … ] cuando quieras uno. |
| .[] | select(.ms > 100) | [{"ms":41},{"ms":998}] | {"ms":998} select conserva la entrada cuando la condición es verdadera y no emite nada cuando es falsa. |
| map(.ms) | [{"ms":41},{"ms":998}] | [41,998] map(f) es [.[] | f] — toma un array y devuelve un array. |
| keys | {"b":1,"a":2} | ["a","b"] keys ORDENA. Usa keys_unsorted para el orden del documento — la misma entrada da ["b","a"]. |
| length | {"a":1,"b":2} | 2 Claves en un objeto, elementos en un array, puntos de código en una cadena («héllo» son 5), valor absoluto en un número, 0 en null. |
| add | [1,2,3] | 6 Suma los elementos de un array — lo que también concatena cadenas y fusiona objetos. |
| group_by(.k) | map({ k: .[0].k, n: length }) | [{"k":"a"},{"k":"a"},{"k":"b"}] | [{"k":"a","n":2},{"k":"b","n":1}] El idioma para contar por campo. group_by ordena primero, así que los grupos vuelven en orden de clave. |
| unique | [3,1,3] | [1,3] Además de quitar duplicados, ordena. Para objetos, unique_by(f). |
| sort_by(-.n) | [{"n":1},{"n":9}] | [{"n":9},{"n":1}] Negar la clave es la forma de ordenar de mayor a menor; sort_by no tiene un flag reverse. |
| to_entries | {"a":1} | [{"key":"a","value":1}] El puente objeto ⇄ lista. from_entries vuelve atrás; en un ARRAY las claves son los índices. |
| with_entries(.value += 1) | {"a":1,"b":2} | {"a":2,"b":3} to_entries | map(f) | from_entries en un solo paso — la manera de mapear sobre los valores de un objeto. |
| del(.b) | {"a":1,"b":2} | {"a":1} Toma una ruta, así que del(.a[1]) y del(.a, .b) también funcionan. |
| .a // "fallback" | {"a":null} | "fallback" Solo entra con null, false y «ninguna salida». {"a":0} da 0 — el cero es verdadero en jq. |
| has("a") | {"a":null} | true Pregunta por la CLAVE, no por el valor — así distingues «falta» de «es null». |
| [paths(scalars)] | {"a":{"b":1}} | [["a","b"]] Todas las rutas hasta una hoja. leaf_paths ya no existe en jq 1.8.2; esto es su sustituto. |
| flatten | [[1,[2]],[3]] | [1,2,3] Hasta el fondo por defecto; flatten(1) para un solo nivel. |
| test("^ERR"; "i") | "error: x" | true Regex de Oniguruma con una cadena de flags. match / capture / sub / gsub / splits toman el mismo par. |
| capture("(?<code>[0-9]{3})") | "status 503 here" | {"code":"503"} Los grupos con nombre pasan a ser claves del objeto — la vía más rápida de una línea de log a campos. |
| @csv | ["web",3] | "web",3 Con -r. Cadenas entrecomilladas, números desnudos, null vacío; un array u objeto anidado es un error de ejecución. @tsv usa un tabulador real. |
| @base64d | "aGVsbG8=" | hello Con -r. El decodificador de secretos de Kubernetes. Un base64 no válido es un error de ejecución, no un silencio. |
| todate | 1700000000 | 2023-11-14T22:13:20Z fromdate vuelve atrás. Para cualquier otro formato, strftime("%Y-%m-%d"). |
| limit(2; .[]) | [1,2,3] | 1 2 Detiene el generador después de n salidas — y es también el freno que vuelve seguro un filtro sin límite. |
| .[1:3] | [1,2,3,4] | [2,3] Corta arrays y cadenas; .[-1:] toma el último elemento. |
| .. | numbers | {"a":[1,2]} | 1 2 .. es el descenso recursivo; numbers / strings / objects / arrays / nulls / booleans filtran por tipo. |
| $__loc__ | null | {"file":"<top-level>","line":1} Dónde estás dentro del programa. El fichero es «<top-level>» — no «<stdin>», diga lo que diga un autocompletado. |
Las salidas se muestran como jq las imprime con -c; las filas de @csv, @base64d y todate dan por hecho -r, porque sin él jq imprime el resultado como una cadena JSON entrecomillada.
Siguiente paso
¿Tu entrada es YAML? Conviértela primero.
jq lee JSON, y un manifiesto de Kubernetes o una configuración de CI son YAML. Pásalo por el conversor JSON ↔ YAML — que además informa de cada comentario, ancla y marca de tiempo que cuesta la conversión — y trae el JSON de vuelta aquí para trocearlo.
4 outputs · -r · 3 ms
output 1 web-7d9f8c-2xk4t
output 2 web-7d9f8c-9pl2m
output 3 api-5b4c7d-qq8rn
output 4 batch-1a2b3c-zzz01 FAQ
Tus preguntas, respondidas.
Toca una pregunta para desplegar la respuesta.
¿Es jq de verdad o una reimplementación en JavaScript?
Es jq de verdad. La página carga jq 1.8.2 compilado a WebAssembly — el programa en C real, 907 KB sin comprimir y entre 250 y 340 KB por la red, según si tu navegador negocia brotli o gzip — y pasa tu filtro por él. La insignia de versión que aparece junto a los flags se lee de ese binario en tiempo de ejecución, no está escrita en la página, así que no puede quedarse desactualizada. Aquí no se aproxima el comportamiento de jq, porque aquí no se reimplementa nada: el mismo código que corre en tu portátil corre en tu pestaña.
¿Mi JSON sale alguna vez de mi navegador?
No. No hay servidor, ni API, ni registro de nada. jq se descarga una sola vez desde este sitio como archivo estático y después se ejecuta por completo dentro de tu pestaña, que es justo la diferencia con un playground que corre en un servidor: con jqplay.org y similares, el JSON que pegas viaja a la máquina de otra persona para ser evaluado. Aquí puedes pegar sin miedo salidas de kubectl de producción, respuestas de API con tokens dentro y líneas de log con datos de clientes.
¿Qué flags están disponibles y cuáles no?
Cuatro interruptores: -r (salida de cadenas en crudo), -s (recoger todo el flujo de entrada en un array), -n (ejecutar una vez con null como entrada) y -c (compacto, una línea por resultado). No están en esta versión: --arg y --argjson, la carga de módulos (-L, include, import — jq responde «module not found»), --seq, la salida en color, los argumentos de fichero y la lectura desde una URL. A --arg puedes sustituirlo dentro del propio programa: ("prod") as $ns | … enlaza un valor igual de bien.
¿Por qué falla aquí el jq que escribió un asistente de IA?
Casi siempre porque usó un builtin que no existe en jq 1.8.2. leaf_paths es el caso clásico — se eliminó, y jq responde «leaf_paths/0 is not defined»; la forma que sí funciona es paths(scalars). Lo mismo pasa con flags inventados y con builtins de otras herramientas (jaq, gojq, JMESPath) que nunca existieron en jq. Un error de compilación aquí cita el mensaje propio de jq, la línea, la columna y el fragmento con el caret, así que ves exactamente qué token rechazó en lugar de adivinarlo.
¿Cuál es la diferencia entre -s e inputs?
-s lee todos los valores del flujo de entrada en un único array y ejecuta tu filtro una vez sobre ese array: 1 2 3 se convierte en [1,2,3]. -n ejecuta el filtro una vez con null como entrada y te entrega el flujo a través del generador inputs, así que [inputs] sobre 1 2 3 también da [1,2,3] — pero tú controlas cuándo se extrae cada valor, y eso es lo que te permite emparejar valores, saltarte un registro de cabecera o parar antes de tiempo. -s lo almacena todo primero; -n con inputs va en flujo.
¿Por qué -r sigue imprimiendo JSON para mi objeto?
Porque -r solo quita las comillas alrededor de los resultados que son cadenas. Todo lo que no sea una cadena — un objeto, un array, un número, un booleano o null — se sigue imprimiendo como JSON, y por eso . sobre {"a":1} se ve idéntico con y sin -r. Si quieres texto a partir de algo que no es una cadena, conviértelo en el filtro: tostring, @csv, @tsv, join(",") o una cadena interpolada como "\(.name) → \(.image)".
¿Cómo saco CSV o TSV de jq?
Construye un array por fila y pásalo por @csv o @tsv, y después activa -r para que la fila se imprima como texto y no como una cadena JSON entre comillas. ["web",3] | @csv da "web",3 — cadenas entrecomilladas, números desnudos — y @tsv da web, luego un tabulador real, luego 3. Los dos rechazan valores anidados: un array o un objeto dentro de una fila es un error de ejecución («array ([\"a\"]) is not valid in a csv row»), y null se convierte en un campo vacío.
¿Qué hace // en realidad?
a // b produce a, salvo que a sea false, null, o no produzca ninguna salida; en ese caso produce b. La trampa es que no significa «si está vacío»: en jq el 0 y la cadena vacía son verdaderos, así que {"a":0} | .a // "fallback" da 0, no "fallback". Si lo que quieres es «cuando falta la clave», pregúntalo explícitamente: if has("a") then .a else "fallback" end.
¿jq redondea los números grandes igual que JavaScript?
No, mientras el valor siga intacto. jq 1.8 conserva el literal que le diste, así que {"n":9007199254740993} | .n imprime exactamente 9007199254740993 — un número que JavaScript no puede representar — y 1.0 sigue siendo 1.0 en lugar de colapsar a 1. En cuanto haces aritmética con él, la garantía termina: .n + 0 pasa a ser 9007199254740992, porque el cálculo va por un doble de 64 bits. Es una propiedad de jq, no del navegador; jq en la línea de comandos responde lo mismo.
¿Qué tamaño de entrada puedo pegar y qué pasa si mi filtro no termina nunca?
La entrada está limitada a 2 MB (2.000.000 de bytes) y el panel de resultados muestra las primeras 200 salidas, siempre con el número real al lado — «Copy all» sigue copiando todas. Un filtro que no termina nunca es lo único que duele de verdad: jq se ejecuta de forma síncrona en esta pestaña, así que bloquea la página hasta que recargues. Que veas una tarjeta de error en su lugar depende de la forma. Si el flujo infinito se recoge — [repeat(1)], [recurse(.a)], length, last —, jq llena su memoria WebAssembly y aborta en uno o dos segundos, y el playground convierte eso en un mensaje de error normal. Si simplemente fluye, un repeat(1) o un recurse(.a) desnudos siguen corriendo: medimos 40 segundos sin ningún aborto. Las dos formas a vigilar son un repeat sin freno y recurse(.field), que llega a null y luego recursa sobre null eternamente — escribe recurse(.field?; . != null), o envuelve el generador en limit(n; …).
More free, private DevOps tools.
El jq Playground es una de las herramientas de OpsCanopy — una copa creciente de validadores, conversores y probadores que funcionan en el navegador y nunca tocan un servidor.
39 herramientas gratuitas, todas pueden funcionar sin conexión — opscanopy.com funciona sin registro y sin subir nada.
Relacionado: el probador de regex para logs para las líneas que todavía no son JSON, el conversor JSON ↔ YAML para convertir un manifiesto en algo que jq pueda leer, y el decodificador de JWT cuando el JSON interesante está dentro de un token — o explora el directorio de herramientas completo.
Se ofrece tal cual, por comodidad; jq es un proyecto de código abierto independiente y esta página no está afiliada a él. OpsCanopy es gratis y abierto.