Skip to content
Voltar ao blog
Tutoriais

Guia rápido do jq: 30 padrões JSON de linha de comando reais

Domine o jq com 30 padrões testados em produção para filtrar, transformar e extrair JSON na linha de comando — de kubectl e AWS CLI a logs.

12 min de leitura

Guia rápido do jq: 30 padrões JSON de linha de comando reais

Você direciona kubectl get pods -o json para o less, e o terminal trava diante de dois megabytes de JSON. Tudo o que você quer é o nome de cada pod na fase Running. O jq faz isso com três caracteres de filtro — desde que você conheça o vocabulário.

Este não é mais um guia de sintaxe. São 30 padrões que você realmente vai digitar, agrupados pela tarefa que está tentando resolver: acessar, filtrar, transformar, agregar, formatar e combinar com ferramentas reais como kubectl, aws e docker.

Quando usar jq, formatador de navegador ou código

jq nem sempre é a resposta certa. As três escolhas honestas são:

SituaçãoFerramenta idealPor quê
Uma resposta de API, com realce de sintaxe e números de linhaJSON Formatter no navegadorDiff visual, zero configuração, privado no navegador
Pipeline de shell, processamento de logs, script de CI, servidor remotojqComponível, scriptável, sem dependência de GUI
Lógica de negócio, testes unitários, ramificações complexasCódigo (JS / Python)Debugger real, tipagem, bibliotecas

Escolha jq quando a tarefa vive dentro de um pipeline de shell — o resto geralmente fica mais fácil em outro lugar.

Instalação e seu primeiro pipeline

O jq chega como binário único em todas as plataformas principais:

# macOS
brew install jq

# Debian / Ubuntu
sudo apt install jq

# Windows (winget)
winget install jqlang.jq

Primeiro pipeline, usando o filtro identidade:

curl -s https://api.github.com/users/octocat | jq .

O filtro . pega a entrada e a devolve inalterada, formatada. Só isso já substitui a maioria dos momentos «deixa eu abrir esse JSON em um editor».

Cinco flags cobrem 90 % do uso real:

FlagFunção
-rSaída crua — remove aspas ao redor de resultados de string
-cCompacto — um valor JSON por linha (NDJSON)
-sSlurp — lê todas as entradas em um único array
-REntrada crua — lê linhas como strings em vez de JSON
-nEntrada nula — não lê stdin, usa null como entrada

O modelo mental central: filtros e pipes

Um filtro recebe um valor JSON como entrada e produz zero ou mais valores JSON como saída. Filtros compõem-se com um pipe |, que envia cada saída do filtro da esquerda como entrada para o da direita. É o mesmo modelo mental de pipes de shell, só que correm valores JSON em vez de bytes.

# . — identidade
echo '{"name":"Alice"}' | jq '.'

# .key — acesso a campo
echo '{"name":"Alice"}' | jq '.name'

# .key.sub — caminho profundo
echo '{"user":{"email":"a@x.com"}}' | jq '.user.email'

# .[] — iterar elementos do array (produz múltiplas saídas)
echo '[{"id":1},{"id":2}]' | jq '.[] | .id'

# Composição com pipe: cada saída de .items[] alimenta .name
echo '{"items":[{"name":"a"},{"name":"b"}]}' | jq '.items[] | .name'

Toda a gramática cabe aqui. Os 30 padrões abaixo são combinações dessas primitivas.

30 padrões que você vai usar de verdade

Cada padrão mostra o JSON de entrada, o comando e a saída. Copie qualquer um direto para o terminal.

Acesso e extração (padrões 1–5)

Padrão 1 — Acesso seguro com ?

Acessar um campo que pode não existir, sem quebrar:

echo '{"name":"Alice"}' | jq '.address?.city?'
# Saída: null

O ? suprime erros em chaves ausentes. Sem ele, .address.city lançaria erro de tipo se .address estivesse faltando.

Padrão 2 — Acesso por caminho profundo

echo '{"user":{"profile":{"email":"a@x.com"}}}' | jq '.user.profile.email'
# Saída: "a@x.com"

Padrão 3 — Fatiamento de array

echo '[10,20,30,40,50]' | jq '.[1:3]'
# Saída: [20, 30]

echo '[10,20,30,40,50]' | jq '.[-1]'
# Saída: 50

Índices negativos contam do fim. Fatias usam intervalos semiabertos, como em Python.

Padrão 4 — Descida recursiva para encontrar toda chave correspondente

echo '{"a":{"name":"x"},"b":[{"name":"y"},{"id":1}]}' | jq '.. | .name? | select(. != null)'
# Saída: "x"
#        "y"

.. percorre todos os valores da árvore. Combinado com .name? e select, extrai cada campo name em qualquer profundidade — indispensável ao explorar esquemas JSON desconhecidos.

Padrão 5 — Listar todas as chaves de um objeto

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys'
# Saída: ["apple", "mango", "zebra"]

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys_unsorted'
# Saída: ["zebra", "apple", "mango"]

keys ordena alfabeticamente; keys_unsorted preserva a ordem de inserção.

Filtrar (padrões 6–10)

Padrão 6 — Filtrar array por condição

echo '[{"age":20},{"age":30},{"age":40}]' | jq 'map(select(.age > 25))'
# Saída: [{"age":30},{"age":40}]

map(f) aplica f a cada elemento; select(cond) mantém apenas os elementos em que a condição é verdadeira.

Padrão 7 — Correspondência de prefixo de string

echo '[{"name":"api-gateway"},{"name":"web-ui"},{"name":"api-auth"}]' \
  | jq '.[] | select(.name | startswith("api"))'
# Saída: {"name":"api-gateway"}
#        {"name":"api-auth"}

Também úteis: endswith("..."), contains("..."), test("^regex$").

Padrão 8 — Condições combinadas

echo '[{"type":"A","count":5},{"type":"A","count":15},{"type":"B","count":20}]' \
  | jq '.[] | select(.type == "A" and .count > 10)'
# Saída: {"type":"A","count":15}

and, or, not se comportam como esperado.

Padrão 9 — Remover campos sensíveis

echo '{"user":"alice","password":"s3cret","token":"abc"}' | jq 'del(.password, .token)'
# Saída: {"user":"alice"}

del() aceita vários caminhos e não falha se algum estiver ausente.

Padrão 10 — Deduplicar por campo

echo '[{"id":1,"v":"a"},{"id":2,"v":"b"},{"id":1,"v":"a2"}]' | jq 'unique_by(.id)'
# Saída: [{"id":1,"v":"a"},{"id":2,"v":"b"}]

unique deduplica valores inteiros; unique_by(f) deduplica pelo resultado de um filtro.

Transformar (padrões 11–15)

Padrão 11 — Renomear campos

echo '[{"first_name":"Alice","age":30}]' | jq 'map({name: .first_name, age})'
# Saída: [{"name":"Alice","age":30}]

A forma curta {age} equivale a {age: .age}.

Padrão 12 — Adicionar campo calculado com interpolação de string

echo '[{"first":"Alice","last":"Chen"}]' \
  | jq 'map(. + {fullName: "\(.first) \(.last)"})'
# Saída: [{"first":"Alice","last":"Chen","fullName":"Alice Chen"}]

\(expr) avalia expr e interpola o valor na string.

Padrão 13 — Achatar arrays aninhados

echo '[{"tags":["a","b"]},{"tags":["c"]}]' | jq '[.[] | .tags[]]'
# Saída: ["a","b","c"]

echo '[[1,2],[3,[4,5]]]' | jq 'flatten'
# Saída: [1,2,3,4,5]

flatten aceita profundidade opcional: flatten(1) remove apenas um nível.

Padrão 14 — Objeto para array e vice-versa

echo '{"a":1,"b":2}' | jq 'to_entries'
# Saída: [{"key":"a","value":1},{"key":"b","value":2}]

echo '[{"key":"a","value":1},{"key":"b","value":2}]' | jq 'from_entries'
# Saída: {"a":1,"b":2}

Esse par habilita transformações que exigem iterar sobre as chaves de um objeto — algo que a sintaxe de pontos não permite diretamente.

Padrão 15 — Mesclar profundamente dois objetos

echo '{"a":{"x":1},"b":2}' | jq '. * {a:{y:9}, c:3}'
# Saída: {"a":{"x":1,"y":9},"b":2,"c":3}

O operador * faz mesclagem profunda. Para mesclagem superficial use + (o lado direito vence).

Agregar (padrões 16–20)

Padrão 16 — Tamanho de arrays, objetos e strings

echo '[1,2,3,4]' | jq 'length'      # 4
echo '{"a":1,"b":2}' | jq 'length'  # 2
echo '"hello"' | jq 'length'        # 5

Padrão 17 — Somar um campo

echo '[{"price":10},{"price":25},{"price":5}]' | jq '[.[].price] | add'
# Saída: 40

add soma números, concatena strings ou funde arrays — conforme o tipo de entrada.

Padrão 18 — Agrupar por campo

echo '[{"cat":"A","n":1},{"cat":"B","n":2},{"cat":"A","n":3}]' | jq 'group_by(.cat)'
# Saída: [[{"cat":"A","n":1},{"cat":"A","n":3}],[{"cat":"B","n":2}]]

Cada grupo vira um array interno. Combine com map para agregar por grupo.

Padrão 19 — Ordenar decrescente

echo '[{"date":"2026-01-03"},{"date":"2026-01-01"},{"date":"2026-01-02"}]' \
  | jq 'sort_by(.date) | reverse'
# Saída: [{"date":"2026-01-03"},{"date":"2026-01-02"},{"date":"2026-01-01"}]

Strings de data ISO 8601 ordenam-se corretamente como strings. Outros formatos exigem parsing antes — o guia do timestamp Unix cobre em detalhe epoch segundos, milissegundos e conversão de fuso horário.

Padrão 20 — Máximo ou mínimo por campo

echo '[{"name":"a","rating":4.1},{"name":"b","rating":4.8},{"name":"c","rating":3.9}]' \
  | jq 'max_by(.rating)'
# Saída: {"name":"b","rating":4.8}

min_by, max_by retornam um único elemento. Top N com sort_by(.rating) | reverse | .[:N].

Formatar saída (padrões 21–25)

Padrão 21 — Saída CSV

echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' \
  | jq -r '.[] | [.name, .age] | @csv'
# Saída: "Alice",30
#        "Bob",25

@csv coloca aspas em strings e escapa as internas. -r remove as aspas externas de JSON, deixando o CSV pronto para pipe. Para o ida e volta completo entre CSV e JSON em um pipeline, consulte o guia de conversão CSV para JSON.

Padrão 22 — Saída TSV

echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' \
  | jq -r '.[] | [.id, .name] | @tsv'
# Saída: 1	Alice
#        2	Bob

Saída separada por tabulação conversa bem com cut, awk e column -t.

Padrão 23 — Saída de string crua

echo '["alpha","beta"]' | jq -r '.[]'
# Saída: alpha
#        beta

Sem -r, cada linha viria com aspas. Saída crua é o que você passa para xargs, while read ou outro comando de shell.

Padrão 24 — NDJSON / JSON Lines

echo '[{"a":1},{"a":2}]' | jq -c '.[]'
# Saída: {"a":1}
#        {"a":2}

Cada linha é um valor JSON autônomo — o formato usado por Kafka, Elasticsearch e a maioria dos loggers estruturados. -c também remove todo espaço interno.

Padrão 25 — Interpolação de string para saída formatada

echo '[{"name":"server-1","cpu":0.73},{"name":"server-2","cpu":0.21}]' \
  | jq -r '.[] | "\(.name): \(.cpu * 100)% CPU"'
# Saída: server-1: 73% CPU
#        server-2: 21% CPU

Ótimo para resumos e linhas de log onde o JSON cru seria ruído.

DevOps na prática (padrões 26–30)

Padrão 26 — kubectl: nomes de todo pod em execução

kubectl get pods -o json \
  | jq -r '.items[] | select(.status.phase=="Running") | .metadata.name'

Pipeline: itera pods, mantém apenas Running, emite o nome como string crua.

Padrão 27 — AWS EC2: IDs de instância com IP público

aws ec2 describe-instances \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, .PublicIpAddress // "none"] | @tsv'

O operador alternativo // fornece um fallback quando o campo é null — evita um null literal na coluna de saída.

Padrão 28 — API do GitHub: mesclar resultados paginados

for p in 1 2 3; do
  curl -s "https://api.github.com/orgs/myorg/repos?per_page=100&page=$p"
done | jq -s 'add | map(.name)'

-s absorve todas as respostas em um array de arrays, add concatena, map(.name) extrai nomes. Padrão comum para qualquer API paginada.

Padrão 29 — Filtrar arquivos de log estruturados

cat app.log | jq -c 'select(.level=="error")'

Assume que o log está em NDJSON (um objeto JSON por linha). Combine com tail -f para monitoramento ao vivo:

tail -f app.log | jq -c 'select(.level=="error") | {ts: .timestamp, msg: .message}'

Padrão 30 — Docker: todos os nomes de imagem em uso

docker inspect $(docker ps -q) | jq -r '.[].Config.Image' | sort -u

Útil para verificar rapidamente quais versões de imagem estão em execução em um host.

Erros comuns e como resolver

Todo usuário de jq tropeça nestes. Saber a solução com antecedência poupa horas.

Cannot iterate over null (null)

O campo de entrada que você tentou iterar era null ou estava ausente. Dois caminhos:

# Opção A: operador opcional
echo '{}' | jq '.items[]?'
# Saída: (nada, sem erro)

# Opção B: operador alternativo com valor padrão
echo '{}' | jq '(.items // [])[]'
# Saída: (nada, sem erro)

Use ? quando quiser pular silenciosamente. Use // [] quando quiser forçar um array vazio concreto para que os filtros seguintes continuem rodando.

Cannot index array with "key"

Você escreveu .foo, mas o valor atual é um array. Adicione [] para iterar:

# Errado
echo '{"users":[{"name":"Alice"}]}' | jq '.users.name'
# Erro: Cannot index array with "name"

# Certo
echo '{"users":[{"name":"Alice"}]}' | jq '.users[].name'
# Saída: "Alice"

Problemas com aspas no shell

Envolva o programa jq inteiro em aspas simples e use aspas duplas internamente para literais de string:

# Funciona em qualquer lugar
jq '.users[] | select(.role == "admin")'

# Quebra — o shell interpreta as aspas duplas primeiro
jq ".users[] | select(.role == \"admin\")"

Casos extremos no PowerShell do Windows

O PowerShell não trata aspas simples do mesmo jeito. Prefira aspas duplas em volta do programa e escape as internas, ou use here-string:

jq "@'
.users[] | select(.role == \"admin\")
'@"

Para qualquer coisa não trivial, salve o filtro em um arquivo .jq e execute jq -f filter.jq.

Uso indevido de -r

-r só afeta resultados de string. Aplicar em um objeto produz um objeto JSON normal:

echo '{"a":1}' | jq -r '.'
# Saída: {"a":1}     ← inalterado; -r não tinha nada para remover

Se você quer um campo específico sem aspas, selecione-o primeiro: jq -r '.a'.

jq rejeita JSON com comentários ou vírgulas finais

echo '{"a": 1, /* nota */ "b": 2,}' | jq .
# parse error: Invalid numeric literal

jq segue estritamente o RFC 8259 JSON — sem comentários, sem vírgulas finais, sem chaves sem aspas. Se o arquivo for JSON5 ou JSONC (comum em arquivos de configuração), remova essas extensões antes de pipear para jq. O guia de formatação JSON5 e JSONC explica quais parsers os suportam e como converter para JSON estrito.

jq vs alternativas: gron, fx, jj, yq

jq não é a única opção, e às vezes outra ferramenta é mais rápida:

FerramentaPonto forteQuando puxar
gronAchata JSON em caminhos grepáveisExplorar esquemas desconhecidos — você não sabe onde está a chave
fxExplorador TUI interativo com realceFolhear JSONs grandes manualmente
jjBem mais rápido que jq, sintaxe limitadaLoops quentes processando milhões de registros
yqMesma linguagem de filtro mas para YAMLManifestos do Kubernetes e configuração de CI
JSON Formatter no navegadorRealce de sintaxe, mensagens precisas, sem instalaçãoDepurar uma resposta única durante o desenvolvimento

Para trabalho diário em shell, jq ganha na composabilidade. Para exploração ocasional, gron costuma ser mais rápido. Para YAML, use yq — não tente yq seguido de jq.

Dicas pro para o dia a dia

Alguns hábitos que fazem o jq parecer natural:

  1. Mantenha um .jqrc em $HOME. Deixe funções auxiliares lá, e elas ficam disponíveis em toda chamada de jq:

    def running: select(.status.phase == "Running");
    def table(f): [f] | @tsv;
  2. Use o jqplay.org para filtros complexos. Cole o JSON à esquerda, itere o filtro à direita, jogue a versão que funciona no script.

  3. Monte seu próprio cheat sheet a partir do history. history | grep 'jq ' | sort -u > ~/jq-patterns.txt captura todo padrão que você realmente usou.

  4. Combine com o JSON Formatter do navegador para esquemas desconhecidos. Explore a estrutura visualmente primeiro para descobrir o caminho necessário, depois escreva o comando jq.

  5. Monitorar valores ao vivo: watch -n 5 "curl -s api.example.com/health | jq '.uptime'" atualiza a cada 5 segundos — um mini dashboard de ops sem dependências.

FAQ

O que é jq e por que desenvolvedores usam?

jq é um processador JSON de linha de comando. Extrai, filtra e transforma JSON em pipelines de shell sem script Python ou Node — o caminho mais curto entre respostas de API, arquivos de log ou saída do kubectl e o campo que você quer.

O jq está disponível no Windows?

Está. Instale com winget install jqlang.jq, Chocolatey choco install jq ou baixe o binário em jqlang.org. As regras de aspas do PowerShell diferem das do bash — na dúvida, salve os filtros em um arquivo .jq e execute jq -f filter.jq.

Em que o jq se diferencia de um formatador JSON de navegador?

Um JSON Formatter de navegador é interativo — você cola JSON, vê realce e erros, copia. jq é não interativo — descreve a transformação uma vez, roda em um pipeline de shell. Use o navegador para depurar uma resposta; use jq para automatizar em centenas de entradas.

Por que o jq diz «Cannot iterate over null»?

Você tentou iterar (.[]) sobre um valor null — normalmente porque o campo faltou na entrada. Corrija com o operador opcional .items[]? ou forneça um padrão com .items // [] | .[].

O jq pode alterar arquivos no lugar?

Não diretamente — o jq escreve em stdout. Use um arquivo temporário ou o sponge do moreutils: jq '.version = "2.0"' config.json | sponge config.json. Faça backup do original antes; um filtro escrito errado sobrescreve o arquivo.

Como uso jq com respostas de curl?

Direcione curl -s para jq. A flag -s silencia a barra de progresso do curl para que só o corpo JSON chegue ao jq:

curl -s https://api.github.com/users/octocat | jq '.name, .blog'

Qual a diferença entre o | do jq e o | do shell?

O pipe do shell passa bytes entre processos. O pipe do jq passa valores JSON entre filtros em uma única invocação. Um comando com vários pipes internos roda em um processo — mais barato que encadear jq | jq | jq.

O jq lida com JSON Lines (NDJSON)?

Sim, nativamente. O jq lê cada linha como um valor JSON independente quando elas estão separadas por espaços. Use -c para emitir NDJSON e -s para coletar NDJSON em um único array.

Como formato JSON sem filtrar nada?

Use o filtro identidade: cat data.json | jq . ou jq . < data.json. Ele analisa, valida e formata com indentação de dois espaços — sem filtro.

Existe alternativa ao jq com interface gráfica?

Existe. O fx oferece uma TUI interativa. Para uma GUI sem instalação, o JSON Formatter baseado em navegador atende a maioria das necessidades de explorar e validar. Ferramentas web como jqplay.org oferecem o próprio jq com prévia ao vivo.

Quando usar jq em vez de escrever um script Python?

Escolha jq quando a tarefa for pontual, couber em um pipeline de shell e permanecer na semântica de filtrar/transformar/extrair. Mude para Python se precisar de testes unitários, estado complexo, bibliotecas de terceiros, ou lógica que exceda a legibilidade de um arquivo .jq.

Como uso expressões regulares no jq?

O jq expõe regex via test("pattern"), match("pattern"), capture("pattern") e scan("pattern"), todos em sintaxe PCRE. Passe flags como segundo argumento: test("abc"; "i") para ignorar maiúsculas/minúsculas. match devolve offsets e capturas; scan emite cada correspondência não sobreposta.

Como preservar caracteres acentuados (ç, ã, é) na saída de jq?

jq emite UTF-8 por padrão e mantém acentos desde que você não use -a / --ascii-output. Se aparecer \u00e7 em vez de ç, geralmente é o locale do terminal: confirme que $LANG é pt_BR.UTF-8 ou en_US.UTF-8 e evite a flag -a.

Pontos-chave

  1. Primeiro o modelo mental: um filtro entra, zero ou mais valores JSON saem, composição com |. O resto é sintaxe.
  2. Aprenda por tarefa, não por operador: os 30 padrões cobrem cerca de 95 % do uso diário do jq.
  3. Trate null explicitamente: ? para pular em silêncio, // default para fallback concreto. A maioria das correções de Cannot iterate over null passa por um desses dois.
  4. Saiba quando jq é a ferramenta errada: respostas únicas pertencem a um JSON Formatter de navegador; YAML pertence ao yq; lógica complexa pertence a código real.
  5. Combine com sua stack existente: jq brilha dentro de curl, kubectl, aws, docker e pipelines de log. Use como cola, não como camada de lógica.

Para fluxos JSON relacionados, veja o guia de formatação JSON5 e JSONC sobre extensões de sintaxe para arquivos de configuração, e o guia de conversão CSV para JSON para migrações de formato onde o jq se encaixa no pipeline. Quando seu JSON tem timestamps, o guia do timestamp Unix cobre as armadilhas ao transformar campos de data.

Artigos relacionados

Ver todos os artigos