Anúncios incomodam? Ir Sem anúncios Hoje

jq One-Liners Filtrar e transformar JSON da linha de comando sem escrever um script

Atualizado em

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.

jq One-Liners: Filtre e transforme JSON da linha de comando sem escrever um script 1
ANUNCIADO Remover?

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 aninhado
  • map(select(...)) — filtrar em uma única passagem; and encadeia condições
  • sort_by(-.stargazers_count) — nega o valor para ordenação decrescente; sort_by(.field) sozinha dá ordenação crescente
  • map({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ê querExpressão jq
Todos os valores de um campomap(.field)
Filtrar itens correspondentesmap(select(.field == "val"))
Redefinir cada objetomap({newKey: .oldKey})
Renomear todas as chavesto_entries | map(.key = ...) | from_entries
Remover camposmap(del(.field1, .field2))
Ordenar em ordem crescentesort_by(.field)
Ordenar em ordem decrescentesort_by(-.field)
Contar por grupogroup_by(.field) | map({key: .[0].field, count: length})
Obter todas as chaves de um objetokeys
Contar itens em um arraylength
Valores únicos de um campomap(.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

Quer eliminar anúncios? Fique sem anúncios hoje mesmo

Instale nossas extensões

Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida

Ao Extensão do Chrome Ao Extensão de Borda Ao Extensão Firefox Ao Extensão Opera

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!

ANUNCIADO Remover?
ANUNCIADO Remover?
ANUNCIADO Remover?

Notícias com destaques técnicos

Envolver-se

Ajude-nos a continuar fornecendo ferramentas gratuitas valiosas

Compre-me um café
ANUNCIADO Remover?