O que jq — Consulta e Transformação de JSON faz?
Regra de Leitura Seletiva
Comece com:
references/senior-master-standard.mdreferences/usage-routing.mdreferences/quality-checklist.md
Em seguida, carregue apenas os documentos herdados, scripts, ativos ou exemplos que correspondem à tarefa real do usuário.
Visão Geral
jq é a ferramenta CLI padrão para consultar e remodelar JSON. Este skill aborda o uso especializado e prático: filtrar dados profundamente aninhados, transformar estruturas, agregar valores e compor jq em pipelines de shell. Cada exemplo está pronto para copiar e colar em fluxos de trabalho reais.
Quando Usar Este Skill
- Use ao analisar a saída JSON de APIs, ferramentas CLI (AWS, GitHub, kubectl, docker) ou arquivos de log
- Use ao transformar a estrutura JSON (renomear chaves, achatar arrays, agrupar registros)
- Use quando o usuário precisar de
jqdentro de um script bash ou one-liner - Use ao explicar o que uma expressão complexa de
jqfaz
Como Funciona
jq pega uma expressão de filtro e a aplica à entrada JSON. Os filtros se compõem com pipes (|), e o jq lida nativamente com arrays, objetos, strings, números, booleanos e null.
Seleção Básica
# Extrair um campo
echo '{"name":"alice","age":30}' | jq '.name'
# "alice"
# Acesso aninhado
echo '{"user":{"email":"[email protected]"}}' | jq '.user.email'
# Índice de array
echo '[10, 20, 30]' | jq '.[1]'
# 20
# Fatia de array
echo '[1,2,3,4,5]' | jq '.[2:4]'
# [3, 4]
# Todos os elementos do array
echo '[{"id":1},{"id":2}]' | jq '.[]'
Filtragem com select
# Manter apenas elementos correspondentes
echo '[{"role":"admin"},{"role":"user"},{"role":"admin"}]' \
| jq '[.[] | select(.role == "admin")]'
# Comparação numérica
curl -s https://api.github.com/repos/owner/repo/issues \
| jq '[.[] | select(.comments > 5)]'
# Testar se um campo existe e não é nulo
jq '[.[] | select(.email != null)]'
# Combinar condições
jq '[.[] | select(.active == true and .score >= 80)]'
Mapeamento e Transformação
# Extrair um campo de cada elemento do array
echo '[{"name":"alice","age":30},{"name":"bob","age":25}]' \
| jq '[.[] | .name]'
# ["alice", "bob"]
# Atalho: map()
jq 'map(.name)'
# Construir um novo objeto por elemento
jq '[.[] | {user: .name, years: .age}]'
# Adicionar um campo calculado
jq '[.[] | . + {senior: (.age > 28)}]'
# Renomear chaves
jq '[.[] | {username: .name, email_address: .email}]'
Agregação e Redução
# Somar todos os valores
echo '[1, 2, 3, 4, 5]' | jq 'add'
# 15
# Somar um campo entre objetos
jq '[.[].price] | add'
# Contar elementos
jq 'length'
# Máximo / mínimo
jq 'max_by(.score)'
jq 'min_by(.created_at)'
# reduce: acumulador personalizado
echo '[1,2,3,4,5]' | jq 'reduce .[] as $x (0; . + $x)'
# 15
# Agrupar por campo
jq 'group_by(.department)'
# Contar por grupo
jq 'group_by(.status) | map({status: .[0].status, count: length})'
Interpolação de Strings e Formatação
# Interpolação de strings
jq -r '.[] | "\(.name) tem \(.age) anos"'
# Formatar como CSV (sem cabeçalho)
jq -r '.[] | [.name, .age, .email] | @csv'
# Formatar como TSV
jq -r '.[] | [.name, .score] | @tsv'
# Codificar valor para URL
jq -r '.query | @uri'
# Codificar em Base64
jq -r '.data | @base64'
Trabalhando com Chaves e Caminhos
# Listar todas as chaves de nível superior
jq 'keys'
# Verificar se a chave existe
jq 'has("email")'
# Excluir uma chave
jq 'del(.password)'
# Excluir chaves aninhadas de cada elemento
jq '[.[] | del(.internal_id, .raw_payload)]'
# Descida recursiva: encontrar todos os valores para uma chave em qualquer lugar na árvore
jq '.. | .id? // empty'
# Obter todos os caminhos de folhas
jq '[paths(scalars)]'
Condicionais e Tratamento de Erros
# if-then-else
jq 'if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end'
# Operador alternativo: usar fallback se for nulo ou falso
jq '.nickname // .name'
# try-catch: pular erros em vez de parar
jq '[.[] | try .nested.value catch null]'
# Suprimir saída nula com // empty
jq '.[] | .optional_field // empty'
Integração Prática com Shell
# Ler de arquivo
jq '.users' data.json
# Saída compacta (sem espaços em branco) para encadeamento
jq -c '.[]' records.json | while IFS= read -r record; do
echo "Processando: $record"
done
# Passar uma variável de shell para jq
STATUS="active"
jq --arg s "$STATUS" '[.[] | select(.status == $s)]'
# Passar um número
jq --argjson threshold 42 '[.[] | select(.value > $threshold)]'
# Engolir várias linhas JSON em um array
jq -s '.' records.ndjson
# Múltiplos arquivos: engolir todos em um array
jq -s 'add' file1.json file2.json
# Pipeline seguro contra nulos a partir de um comando
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
# GitHub CLI: extrair números de PR
gh pr list --json number,title | jq -r '.[] | "\(.number)\t\(.title)"'
# AWS CLI: listar IDs de instâncias em execução
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
# Docker: mostrar nomes e imagens de contêineres
docker inspect $(docker ps -q) | jq -r '.[] | "\(.Name)\t\(.Config.Image)"'
Padrões Avançados
# Transpor um objeto de arrays para um array de objetos
# Entrada: {"names":["a","b"],"scores":[10,20]}
jq '[.names, .scores] | transpose | map({name: .[0], score: .[1]})'
# Achatar um nível
jq 'flatten(1)'
# Único por campo
jq 'unique_by(.email)'
# Ordenar, deduplicar e re-indexar
jq '[.[] | .name] | unique | sort'
# Walk: aplicar transformação a cada nó recursivamente
jq 'walk(if type == "string" then ascii_downcase else . end)'
# env: ler variáveis de ambiente dentro de jq
export API_KEY=secret
jq -n 'env.API_KEY'
Práticas Recomendadas
- Sempre use
-r(saída bruta) ao passar resultados dejqpara variáveis de shell ou outros comandos para remover as aspas das strings JSON - Use
--arg/--argjsonpara injetar variáveis de shell com segurança — nunca interpole variáveis de shell diretamente em strings de filtro - Prefira
map(f)em vez de[.[] | f]para legibilidade - Use
-c(compacto) para pipelines JSON delimitados por nova linha; omita para depuração legível por humanos - Teste filtros interativamente com
jq -ne entrada literal antes de incorporar em scripts - Use
emptypara descartar elementos indesejados em vez de filtrar paranull
Notas de Segurança
jqé somente leitura por design — não pode escrever arquivos ou executar comandos- Evite incorporar valores de campos JSON não confiáveis diretamente em comandos shell; sempre cite ou use
--arg
Armadilhas Comuns
-
Problema:
jqgeranullem vez do valor esperado Solução: Verifique erros de digitação nos nomes das chaves; usekeyspara inspecionar os nomes reais dos campos. Lembre-se de que JSON diferencia maiúsculas de minúsculas. -
Problema: Números são citados como strings na saída Solução: Use
--argjsonem vez de--argao injetar valores numéricos. -
Problema: O filtro funciona no terminal, mas falha em um script Solução: Certifique-se de que a string do filtro use aspas simples no shell para evitar expansão de variáveis. Exemplo:
jq '.field'nãojq ".field". -
Problema:
addretornanullem um array vazio Solução: Useadd // 0ouadd // ""para fornecer um padrão de fallback. -
Problema: Transmitir arquivos grandes é lento Solução: Use
jq --streamou mude parajstream/gronpara arquivos muito grandes.
Skills Relacionados
@bash-pro— Incorporar chamadas jq em scripts shell robustos@bash-linux— Padrões gerais de pipeline de shell@github-automation— Usar jq com saída JSON do GitHub CLI
Limitações
- Use este skill apenas quando a tarefa corresponder claramente ao escopo descrito acima.
- Não trate a saída como um substituto para validação, teste ou revisão especializada específica do ambiente.
- Pare e peça esclarecimentos se as entradas, permissões, limites de segurança ou critérios de sucesso necessários estiverem ausentes.