Pular para o conteúdo

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 1.8.2 real (WebAssembly) Roda no seu navegador Sem cadastro Atualizado em 31 de jul. de 2026

jq Playground

Examples
filter.jq program
Flags

-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.

input.json stdin

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.

Result

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.

  1. 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.

  2. 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".

  3. 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.

  4. 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.

stdin
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.

results.txt
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.

results.txt
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.

É 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.

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.

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.

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.

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.

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)".

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.

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.

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.

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.