jq One-Liners Filtrar e transformar JSON da linha de comando sem escrever um script
Sete receitas práticas de jq para desenvolvedores de backend e DevOps — abrangendo select, map, to_entries, del, group_by e transformação de APIs reais. Entrada e saída mostradas para cada padrão.
Você está vendo uma resposta minificada de uma API no seu terminal. Você precisa extrair 3 campos, filtrar os nulos e pipelinar o resultado para algo else. Escrever um script em Python para isso exige 20 linhas e 2 minutos que você não tem. jq isso é feito em uma única comando — se você conhece os padrões.
Sete receitas abaixo. Cada uma aborda um padrão que você verá repetidamente ao trabalhar com respostas de API ou arquivos de log. Entrada, comando e saída são mostrados para cada receita.
Instalar
brew install jq # macOS
apt-get install jq # Ubuntu/Debian
apk add jq # Alpine (Docker images)
Receita 1: Extrair um campo de cada objeto em um array
A coisa mais comum que você fará com jq: extrair um campo de cada item em um array JSON.
Entrada (users.json)
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"},
{"id": 2, "name": "Bob", "email": "bob@example.com", "role": "user"},
{"id": 3, "name": "Carol", "email": "carol@example.com", "role": "user"}
]
jq '.[].name' users.json
# → "Alice"
# "Bob"
# "Carol" (newline-separated stream)
.[] itera sobre cada elemento do array; .name extrai o campo. A saída é um fluxo — útil para pipelinar para outros comandos. Se você precisar de um array JSON completo:
jq 'map(.name)' users.json
# → ["Alice", "Bob", "Carol"]
map(.name) é abreviação de [.[] | .name] — aplica a expressão a cada item e envolve os resultados em um array. Você usará map() muito.
Receita 2: Filtrar com select
Mantenha apenas os objetos que correspondem a uma condição; descarte os demais.
jq 'map(select(.role == "admin"))' users.json
[
{"id": 1, "name": "Alice", "email": "alice@example.com", "role": "admin"}
]
select(expr) passa o item apenas quando a expressão for verdadeira — tudo o resto desaparece. Envolver em map() mantém a saída como um array. Mais exemplos:
# Numeric comparison
jq 'map(select(.score > 80))' results.json
# Not-null check
jq 'map(select(.error != null))' events.json
# String contains (requires test)
jq 'map(select(.message | test("timeout")))' logs.json
Receita 3: Redefinir objetos com map
Selecione apenas os campos que precisa e renomeie-os opcionalmente na mesma passagem.
jq 'map({name: .name, role: .role})' users.json
[
{"name": "Alice", "role": "admin"},
{"name": "Bob", "role": "user"},
{"name": "Carol", "role": "user"}
]
Você está construindo um novo objeto literal para cada item. Para renomear uma chave, altere a parte esquerda do colão:
jq 'map({username: .name, access_level: .role})' users.json
Uma abreviação que economiza teclas: {name} é equivalente a {name: .name}. Se você quiser um campo sem alteração, não precisa escrever a chave duas vezes:
jq 'map({id, name, role})' users.json
Receita 4: Renomear chaves com to_entries e from_entries
map é útil quando você sabe quais chaves existem. Quando você precisa transformar as chaves em si — adicionar um prefixo, converter convenções de nomenclatura ou renomear com base em uma consulta — to_entries é o padrão certo.
Entrada (config.json)
{"api_url": "https://api.example.com", "timeout": 30, "retry_count": 3}
# Add cfg_ prefix to every key
jq 'to_entries | map(.key = "cfg_" + .key) | from_entries' config.json
{"cfg_api_url": "https://api.example.com", "cfg_timeout": 30, "cfg_retry_count": 3}
to_entries transforma {"k": "v"} em [{"key": "k", "value": "v"}]. Após mutar as entradas no array resultante, from_entries reconstrói o objeto. Para renomear uma chave específica sem tocar as demais:
jq 'to_entries | map(if .key == "api_url" then .key = "endpoint" else . end) | from_entries' config.json
Receita 5: Remover campos com del
O inverso de redefinir: mantenha tudo e remova alguns campos específicos. O uso principal é remover dados sensíveis antes de registrar ou antes de passar um payload para um serviço terceiro.
jq 'map(del(.email))' users.json
[
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"},
{"id": 3, "name": "Carol", "role": "user"}
]
Remova múltiplos campos de uma vez, ou remova caminhos aninhados:
# Multiple top-level fields at once
jq 'del(.password, .token, .refresh_token)' user.json
# Nested path
jq 'del(.user.internal_id)' response.json
# All fields named "debug" at any depth (recursive descent)
jq 'del(.. | .debug? // empty)' response.json
Receita 6: Filtrar, redefinir e ordenar em uma única passagem
O verdadeiro benefício é encadear esses primitivos. Aqui está um padrão que aparece constantemente ao trabalhar com respostas paginadas de API: descer em um array aninhado, filtrar, redefinir os objetos e ordenar o resultado.
Entrada (repos.json)
{
"total_count": 3,
"items": [
{"id": 1, "name": "repo-alpha", "stargazers_count": 142, "language": "Go", "private": false},
{"id": 2, "name": "repo-beta", "stargazers_count": 89, "language": "Python", "private": true},
{"id": 3, "name": "repo-gamma", "stargazers_count": 310, "language": "Go", "private": false}
]
}
jq '.items
| map(select(.private == false and .language == "Go"))
| sort_by(-.stargazers_count)
| map({name, stars: .stargazers_count})' repos.json
[
{"name": "repo-gamma", "stars": 310},
{"name": "repo-alpha", "stars": 142}
]
O pipeline:
.items— descer no array aninhadomap(select(...))— filtrar em uma única passagem;andencadeia condiçõessort_by(-.stargazers_count)— nega o valor para ordenação decrescente;sort_by(.field)sozinha dá ordenação crescentemap({name, stars: .stargazers_count})— reshape final;{name}é abreviação de{name: .name}
Receita 7: Contar níveis de log com group_by
Análise de frequência em saídas estruturadas de log — sem necessidade de banco de dados, sem gymnastics de awk.
Entrada (logs.json)
[
{"level": "error", "msg": "connection timeout", "service": "auth"},
{"level": "info", "msg": "request received", "service": "api"},
{"level": "error", "msg": "null pointer exception", "service": "worker"},
{"level": "warn", "msg": "slow query detected", "service": "db"},
{"level": "error", "msg": "rate limit exceeded", "service": "api"}
]
jq 'group_by(.level) | map({level: .[0].level, count: length}) | sort_by(-.count)' logs.json
[
{"level": "error", "count": 3},
{"level": "info", "count": 1},
{"level": "warn", "count": 1}
]
group_by(.level) retorna um array de arrays — cada sub-array contém todas as entradas que compartilham o mesmo valor de nível. .[0].level extrai o nome do nível do primeiro item do grupo; length conta quantas entradas estão no grupo.
Adicione uma divisão por serviço na mesma consulta:
jq 'group_by(.level) | map({
level: .[0].level,
count: length,
services: map(.service) | unique
})' logs.json
Referência Rápida
Os padrões acima em forma de tabela para quando você precisa de um lembrete rápido:
| O que você quer | Expressão jq |
|---|---|
| Todos os valores de um campo | map(.field) |
| Filtrar itens correspondentes | map(select(.field == "val")) |
| Redefinir cada objeto | map({newKey: .oldKey}) |
| Renomear todas as chaves | to_entries | map(.key = ...) | from_entries |
| Remover campos | map(del(.field1, .field2)) |
| Ordenar em ordem crescente | sort_by(.field) |
| Ordenar em ordem decrescente | sort_by(-.field) |
| Contar por grupo | group_by(.field) | map({key: .[0].field, count: length}) |
| Obter todas as chaves de um objeto | keys |
| Contar itens em um array | length |
| Valores únicos de um campo | map(.field) | unique |
Antes de começar: Domine o Bloco
As respostas de API geralmente chegam minificadas ou profundamente aninhadas. Se você não tiver certeza sobre o caminho que precisa, cole o JSON no Formatador JSON — ele formata com nós colapsáveis para que você possa identificar o caminho antes de escrever a jq expressão. Após executar uma transformação, a ferramenta é útil para verificar a diferença antes e depois quando você está redefinindo ou removendo campos e deseja confirmar que nada mudou inesperadamente. Comparação JSON Esses sete padrões cobrem a maior parte do trabalho com JSON que você fará na linha de comando. O verdadeiro poder está em encadear esses padrões — uma vez que você consiga filtrar, redefinir e ordenar, você pode processar a maioria das respostas de API sem tocar em um arquivo de script.
jq One-Liners: Filtrar e transformar JSON da linha de comando sem escrever um script 2
Instale nossas extensões
Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida
恵 O placar chegou!
Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!
Ferramentas essenciais
Ver tudo Novas chegadas
Ver tudoAtualizar: Nosso ferramenta mais recente foi adicionado em 10 de junho de 2026
