jq Playground · Logs
jq Playground — teste expressões jq online.
Não é uma reimplementação e não é uma ida e volta a um servidor: é o binário real do jq 1.8.2, compilado para WebAssembly e rodando dentro desta aba. Cole o seu JSON, escreva o filtro e veja cada saída que o jq emite — junto com o erro exato que ele imprimiria se o filtro estiver errado.
Roda no seu navegador — nada do que você cola sai desta página. Como comprovamos isso
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.
A lacuna
Builtins inventados — e o servidor de outra pessoa.
Peça uma linha de jq a um assistente e você recebe algo que parece exatamente certo e falha na primeira execução. A falha favorita é um builtin que não existe: leaf_paths saiu do jq 1.8.2, então o jq responde leaf_paths/0 is not defined — e a solução, paths(scalars), não é a que disseram para você. O mesmo acontece com flags emprestadas do jaq e do gojq, e com afirmações muito confiantes sobre // que quebram silenciosamente no 0.
A outra opção é um playground que roda no servidor, o que funciona — fazendo upload do JSON que você só queria inspecionar. Uma troca estranha para a saída de kubectl get secret, para uma resposta de API com um token bearer dentro, ou para uma linha de log com o e-mail de um cliente.
Esta página responde com verdade verificável. O jq que roda aqui é o programa em C, compilado para WebAssembly, baixado uma vez deste site e executado na sua aba — e o selo de versão ao lado das flags é lido desse binário em vez de digitado na página. Cada resultado de builtin da tabela de referência abaixo saiu do mesmo binário e está fixado por um teste, então esta página não consegue se afastar do que o jq realmente faz.
Trabalhando com logs em vez de JSON? O testador de regex para logs faz o mesmo trabalho com linhas sem estrutura.
O caminho
Como funciona.
Quatro passos, todos dentro da aba do seu navegador — e o terceiro é o binário do jq de verdade, não uma imitação.
-
Baixar o binário real, uma vez.
jq 1.8.2 como WebAssembly — 907 KB sem compressão, de 250 a 340 KB pela rede dependendo da codificação que o seu navegador negociar — servido por este site como arquivo estático com hash no nome e guardado no cache do seu navegador. Ele carrega enquanto você lê, não enquanto você espera.
-
Compilar o filtro.
O jq compila o seu programa antes de ver qualquer entrada. Um erro de sintaxe ou uma função não definida terminam com código 3 — e você recebe a mensagem do próprio jq, com linha, coluna e o trecho com o caret, não um "expressão inválida".
-
Rodar sobre a sua entrada.
Seu JSON chega ao jq pela stdin, só com as flags que aparecem na linha de flags. O jq emite um stream de resultados, e cada um vira o seu próprio cartão — porque um stream de quatro valores não é a mesma resposta que um array de quatro.
-
Classificar o que voltou.
O jq usa o código de saída 5 para duas coisas: um erro de execução e uma entrada que não dá para parsear. Aqui as duas são distinguidas pelo prefixo da stderr e apontadas para o editor a que pertencem. As saídas produzidas antes da falha são preservadas, e tudo o que o jq escreveu na stderr é mostrado mesmo quando ele terminou com 0.
Na prática
O jq pode falhar duas vezes e ainda assim sair com 0.
O código de saída do jq reflete apenas a ÚLTIMA entrada processada. Dê a ele um stream em que dois valores quebram o filtro e o último não, e um passo de CI que confere $? vê uma execução limpa.
Cinco entradas, duas delas erradas
Um stream de cinco valores JSON e o filtro .+1. Strings não podem ser somadas a números, então duas das cinco falham.
1 "x" 2 "y" 3 Três resultados, dois erros, saída 0
O playground mostra as três saídas E as duas linhas de stderr, e explica por que o código de saída é 0 — mova a string para o fim do stream e o mesmo filtro termina com 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 Experimente acima: o painel de resultados lista as duas linhas de stderr em "jq also wrote to stderr", com o código de saída ao lado. Nada é escondido só porque o jq considerou a execução um sucesso.
Referência
Os builtins do jq que você realmente usa.
26 filtros, cada um com uma entrada real e a saída exata que o jq 1.8.2 produziu para ela. Digite o filtro de qualquer linha no playground acima e veja rodar nos seus próprios dados.
| Filtro | Entrada | Saída — jq 1.8.2 |
|---|---|---|
| .a.b | {"a":{"b":42}} | 42 Acesso por caminho. Uma chave que falta é null, não um erro — indexar algo que não é objeto é: .a em [1,2] falha com "Cannot index array with string". |
| .items[] | .name | {"items":[{"name":"web"},{"name":"api"}]} | "web" "api" DUAS saídas, não um array. Envolva o filtro todo em [ … ] quando você quiser um. |
| .[] | select(.ms > 100) | [{"ms":41},{"ms":998}] | {"ms":998} O select mantém a entrada quando a condição é verdadeira e não emite nada quando é falsa. |
| map(.ms) | [{"ms":41},{"ms":998}] | [41,998] map(f) é [.[] | f] — recebe um array e devolve um array. |
| keys | {"b":1,"a":2} | ["a","b"] keys ORDENA. Use keys_unsorted para a ordem do documento — a mesma entrada dá ["b","a"]. |
| length | {"a":1,"b":2} | 2 Chaves para objeto, elementos para array, code points para string ("héllo" é 5), valor absoluto para número, 0 para null. |
| add | [1,2,3] | 6 Soma os elementos de um array — o que também concatena strings e mescla objetos. |
| group_by(.k) | map({ k: .[0].k, n: length }) | [{"k":"a"},{"k":"a"},{"k":"b"}] | [{"k":"a","n":2},{"k":"b","n":1}] O idioma de contar por campo. O group_by ordena primeiro, então os grupos voltam na ordem das chaves. |
| unique | [3,1,3] | [1,3] Ordena além de remover duplicatas. Para objetos, unique_by(f). |
| sort_by(-.n) | [{"n":1},{"n":9}] | [{"n":9},{"n":1}] Negar a chave é como se ordena de forma decrescente; sort_by não tem flag reverse. |
| to_entries | {"a":1} | [{"key":"a","value":1}] A ponte objeto ⇄ lista. from_entries volta; em um ARRAY as chaves são os índices. |
| with_entries(.value += 1) | {"a":1,"b":2} | {"a":2,"b":3} to_entries | map(f) | from_entries em um único passo — o jeito de mapear sobre os valores de um objeto. |
| del(.b) | {"a":1,"b":2} | {"a":1} Recebe um caminho, então del(.a[1]) e del(.a, .b) também funcionam. |
| .a // "fallback" | {"a":null} | "fallback" Só entra em null, false e "nenhuma saída". {"a":0} dá 0 — o zero é verdadeiro no jq. |
| has("a") | {"a":null} | true Pergunta pela CHAVE, não pelo valor — é assim que se distingue "não existe" de "é null". |
| [paths(scalars)] | {"a":{"b":1}} | [["a","b"]] Todo caminho até uma folha. leaf_paths não existe mais no jq 1.8.2; isto é o substituto. |
| flatten | [[1,[2]],[3]] | [1,2,3] Até o fundo por padrão; flatten(1) para um nível. |
| test("^ERR"; "i") | "error: x" | true Regex Oniguruma com uma string de flags. match / capture / sub / gsub / splits recebem o mesmo par. |
| capture("(?<code>[0-9]{3})") | "status 503 here" | {"code":"503"} Grupos nomeados viram chaves de objeto — o caminho mais rápido de uma linha de log para campos. |
| @csv | ["web",3] | "web",3 Com -r. Strings entre aspas, números sem nada, null vazio; um array ou objeto aninhado é erro de execução. O @tsv usa uma tabulação real. |
| @base64d | "aGVsbG8=" | hello Com -r. O decodificador de secrets do Kubernetes. Um base64 inválido é erro de execução, não silêncio. |
| todate | 1700000000 | 2023-11-14T22:13:20Z fromdate volta. Para qualquer outro formato, strftime("%Y-%m-%d"). |
| limit(2; .[]) | [1,2,3] | 1 2 Para o gerador depois de n saídas — e é também o freio que torna seguro um filtro sem limite. |
| .[1:3] | [1,2,3,4] | [2,3] Corta arrays e strings; .[-1:] pega o último elemento. |
| .. | numbers | {"a":[1,2]} | 1 2 .. é a descida recursiva; numbers / strings / objects / arrays / nulls / booleans filtram por tipo. |
| $__loc__ | null | {"file":"<top-level>","line":1} Onde você está no programa. O arquivo é "<top-level>" — não "<stdin>", diga o que disser um autocomplete. |
As saídas são mostradas como o jq as imprime com -c; as linhas de @csv, @base64d e todate pressupõem -r, porque sem ele o jq imprime o resultado como uma string JSON entre aspas.
Próximo passo
Sua entrada é YAML? Converta primeiro.
O jq lê JSON, e um manifesto do Kubernetes ou uma configuração de CI é YAML. Passe pelo conversor JSON ↔ YAML — que ainda reporta cada comentário, âncora e timestamp que a conversão custa — e traga o JSON de volta para cá para fatiar.
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
Suas perguntas, respondidas.
Toque em uma pergunta para expandir a resposta.
Isto é o jq de verdade ou uma reimplementação em JavaScript?
É o jq de verdade. A página carrega o jq 1.8.2 compilado para WebAssembly — o programa em C real, 907 KB sem compressão e de 250 a 340 KB pela rede, dependendo de o seu navegador negociar brotli ou gzip — e passa o seu filtro por ele. O selo de versão ao lado das flags é lido desse binário em tempo de execução, não está escrito na página, então não tem como ficar desatualizado. Aqui nada aproxima o comportamento do jq, porque aqui nada o reimplementa: o mesmo código que roda no seu notebook roda na sua aba.
Meu JSON sai do meu navegador em algum momento?
Não. Não existe servidor, nem API, nem log. O jq é baixado uma única vez deste site como arquivo estático e depois roda inteiramente dentro da sua aba — e é exatamente aí que está a diferença em relação a um playground que roda no servidor: no jqplay.org e semelhantes, o JSON que você cola vai para a máquina de outra pessoa para ser avaliado. Aqui você pode colar sem medo saídas de kubectl de produção, respostas de API com tokens dentro e linhas de log com dados de clientes.
Quais flags estão disponíveis e quais não estão?
Quatro chaves: -r (saída de strings em cru), -s (juntar todo o stream de entrada em um array), -n (rodar uma vez com null como entrada) e -c (compacto, uma linha por resultado). Não estão nesta versão: --arg e --argjson, o carregamento de módulos (-L, include, import — o jq responde "module not found"), --seq, saída colorida, argumentos de arquivo e leitura a partir de uma URL. O --arg pode ser substituído dentro do próprio programa: ("prod") as $ns | … vincula um valor do mesmo jeito.
Por que o jq que um assistente de IA escreveu falha aqui?
Quase sempre porque ele usou um builtin que não existe no jq 1.8.2. leaf_paths é o caso clássico — foi removido, e o jq responde "leaf_paths/0 is not defined"; a grafia que funciona é paths(scalars). O mesmo acontece com flags inventadas e com builtins de outras ferramentas (jaq, gojq, JMESPath) que nunca existiram no jq. Um erro de compilação aqui cita a mensagem do próprio jq, com linha, coluna e o trecho com o caret, então você vê exatamente qual token foi rejeitado em vez de adivinhar.
Qual é a diferença entre -s e inputs?
O -s lê todos os valores do stream de entrada em um único array e roda o seu filtro uma vez sobre esse array: 1 2 3 vira [1,2,3]. O -n roda o filtro uma vez com null como entrada e entrega o stream para você pelo gerador inputs, então [inputs] em 1 2 3 também dá [1,2,3] — mas você controla quando cada valor é puxado, e é isso que permite emparelhar valores, pular um registro de cabeçalho ou parar mais cedo. O -s guarda tudo primeiro; o -n com inputs trabalha em stream.
Por que o -r continua imprimindo JSON para o meu objeto?
Porque o -r só remove as aspas em volta dos resultados que são strings. Tudo o que não é string — objeto, array, número, booleano ou null — continua sendo impresso como JSON, e é por isso que . em {"a":1} fica idêntico com e sem -r. Se você quer texto a partir de algo que não é string, converta no filtro: tostring, @csv, @tsv, join(",") ou uma string interpolada como "\(.name) → \(.image)".
Como eu tiro CSV ou TSV do jq?
Monte um array por linha e passe por @csv ou @tsv, e depois ligue o -r para que a linha saia como texto e não como uma string JSON entre aspas. ["web",3] | @csv dá "web",3 — strings entre aspas, números sem nada — e @tsv dá web, depois uma tabulação real, depois 3. Os dois recusam valores aninhados: um array ou objeto dentro de uma linha é erro de execução ("array ([\"a\"]) is not valid in a csv row"), e null vira um campo vazio.
O que o // faz de verdade?
a // b produz a, a menos que a seja false, null, ou não produza saída nenhuma — nesse caso produz b. A pegadinha é que isso não significa "se estiver vazio": no jq o 0 e a string vazia são verdadeiros, então {"a":0} | .a // "fallback" dá 0, e não "fallback". Se você quer mesmo dizer "quando a chave não existe", pergunte isso: if has("a") then .a else "fallback" end.
O jq arredonda números grandes do jeito que o JavaScript faz?
Não enquanto o valor estiver intocado. O jq 1.8 preserva o literal que você deu, então {"n":9007199254740993} | .n imprime exatamente 9007199254740993 — um número que o JavaScript não consegue representar — e 1.0 continua 1.0 em vez de virar 1. Assim que você faz aritmética, a garantia acaba: .n + 0 vira 9007199254740992, porque a conta passa por um double de 64 bits. Isso é uma propriedade do jq, não do navegador; o jq na linha de comando responde igual.
Qual o tamanho de entrada que eu posso colar, e se o meu filtro nunca terminar?
A entrada é limitada a 2 MB (2.000.000 de bytes) e o painel de resultados mostra as primeiras 200 saídas, sempre com a contagem real ao lado — o "Copy all" continua copiando todas. Um filtro que nunca termina é a única coisa que realmente machuca: o jq roda de forma síncrona nesta aba, então ele trava a página até você recarregar. Se você vai ver um cartão de erro no lugar disso depende da forma. Se o fluxo infinito for coletado — [repeat(1)], [recurse(.a)], length, last —, o jq enche a memória WebAssembly e aborta em um ou dois segundos, e o playground transforma isso em uma mensagem de erro comum. Se ele só fluir, um repeat(1) ou um recurse(.a) pelados continuam rodando: medimos 40 segundos sem nenhum abort. As duas formas para ficar de olho são um repeat sem freio e recurse(.field), que chega em null e depois recursa em null para sempre — escreva recurse(.field?; . != null), ou embrulhe o gerador em limit(n; …).
More free, private DevOps tools.
O jq Playground é uma das ferramentas do OpsCanopy — uma copa crescente de validadores, conversores e testadores que rodam no navegador e nunca tocam um servidor.
39 ferramentas gratuitas, todas capazes de funcionar offline — o opscanopy.com não exige cadastro e não envia nada.
Relacionados: o testador de regex para logs para as linhas que ainda não são JSON, o conversor JSON ↔ YAML para transformar um manifesto em algo que o jq consiga ler, e o decodificador de JWT quando o JSON interessante está dentro de um token — ou navegue pelo diretório de ferramentas completo.
Fornecido como está, por conveniência; o jq é um projeto open source separado e esta página não tem vínculo com ele. OpsCanopy é gratuito e aberto.