Formatar JSON em Bash com jq — Guia e Validação
Use o Formatador e Embelezador JSON gratuito diretamente no seu navegador — sem instalação.
Experimentar Formatador e Embelezador JSON online →Quando um script de deploy começa a processar respostas de API ou validar arquivos de configuração em CI, saber como formatar JSON em bash rapidamente se torna essencial. As duas ferramentas que cobrem 99% dos casos do mundo real são jq e python3 -m json.tool — ambas podem lidar com pipelines de format json bash de forma confiável, validar com códigos de saída e integrar-se facilmente a fluxos de trabalho CI/CD. Para inspeções pontuais sem terminal, o Formatador JSON baseado no navegador resolve instantaneamente. Este guia cobre instalação do jq, formatação via pipe e arquivo, funções de validação, integração CI/CD no GitHub Actions, hooks pre-commit, padrões heredoc e quando recorrer ao fallback da stdlib do Python.
- •
jq .formata E valida simultaneamente — sai com código 1 em JSON inválido - • Use
jq -eem pipelines de CI: saída não-zero em output vazio/false/null - •
jq . file.json > /dev/null && echo "valid"— valida sem alterar a saída - •
python3 -m json.toolfunciona em qualquer sistema sem instalação adicional - • Nunca faça
jq . f.json > f.json— o shell trunca o arquivo fonte antes que o jq o leia
O que é Formatação de JSON em Bash?
Formatação de JSON em bash significa transformar JSON compacto e minificado em saída indentada e legível por humanos. Os dados subjacentes não mudam — apenas os espaços em branco e as quebras de linha diferem. Em contextos de scripting, isso importa por dois motivos: legibilidade ao depurar e validação quando o formatador verifica a sintaxe como efeito colateral. Ferramentas como jq analisam o JSON completamente antes de reformatá-lo, o que significa que uma execução de formatação bem-sucedida é também uma verificação implícita de validade. Esse comportamento dual — formatar e validar em uma única etapa — é o que torna o jq tão útil em pipelines automatizados.
{"service":"payments-api","version":"2.4.1","database":{"host":"db-prod-01.internal","port":5432,"pool_size":20},"cache":{"enabled":true,"ttl":300}}{
"service": "payments-api",
"version": "2.4.1",
"database": {
"host": "db-prod-01.internal",
"port": 5432,
"pool_size": 20
},
"cache": {
"enabled": true,
"ttl": 300
}
}jq — Formatar JSON em Bash
jq é o padrão de facto para processamento de JSON em scripts de shell (jq 1.6+, bash 4+). É um processador JSON de linha de comando criado especificamente para formatar, filtrar, transformar e validar JSON. O filtro de identidade . passa o input sem alterações, mas formatado. Quando o jq não consegue analisar o input, sai com código 1 — é isso que o torna ideal para scripting: formatação e validação são uma única operação.
Instalar o jq
# macOS brew install jq # Debian / Ubuntu apt-get install -y jq # Fedora / RHEL / CentOS dnf install jq # Alpine (imagens Docker) apk add --no-cache jq # Verificar jq --version # jq-1.7.1
Formatar a partir do stdin e de um arquivo
# Redirecionar JSON inline pelo jq
echo '{"host":"db-prod-01.internal","port":5432}' | jq .
# Formatar um arquivo diretamente (exibe no stdout)
jq . config/feature-flags.json
# Formatar com indentação de 4 espaços
jq --indent 4 . config/feature-flags.json
# Formatar usando tabulações em vez de espaços
jq --tab . config/feature-flags.jsonGravar a saída formatada em um arquivo
# Salvar a saída formatada (NÃO redirecionar para o mesmo arquivo) jq . compact.json > formatted.json # Compacto (minificar) — inverso da formatação jq -c . formatted.json
jq sai com código 1 em JSON inválido, código 0 em sucesso e código 5 em erros de uso. Use-o em instruções if e guardas || exit 1 em seus scripts.Ordenar chaves e remover cor
# Ordenar todas as chaves alfabeticamente (útil para diffs determinísticos) jq --sort-keys . config/app-config.json # Desativar saída colorida ao gravar em um arquivo de log jq --monochrome-output . response.json >> deploy.log
Referência de Opções do jq
As flags do jq mais usadas para fluxos de trabalho de formatação e validação:
Validar JSON em um Script Bash
Validação e formatação são a mesma operação no jq — ele analisa antes de imprimir. Redirecione stdout para /dev/null quando você só quiser o código de saída sem a saída formatada. O padrão abaixo é reutilizável em scripts de deploy, hooks pre-commit e pipelines de CI. Em resposta a incidentes, a primeira coisa que faço com um payload de API desconhecido é redirecioná-lo pelo jq — ele transforma uma parede de JSON minificado em algo que posso realmente ler e depurar.
Função de validação reutilizável
validate_json() {
local file="$1"
if jq . "$file" > /dev/null 2>&1; then
echo "✓ JSON válido: $file"
return 0
else
echo "✗ JSON inválido: $file" >&2
return 1
fi
}Abortar um deploy em configuração inválida
CONFIG="infra/k8s/app-config.json"
validate_json "$CONFIG" || { echo "Abortando deploy: configuração inválida" >&2; exit 1; }Validar todos os arquivos JSON em um diretório
find ./config -name "*.json" | while read -r f; do jq . "$f" > /dev/null 2>&1 || echo "INVÁLIDO: $f" done
-e / --exit-status vai além: também sai com código 1 quando a saída é false ou null. Use-o para afirmar que um campo específico é verdadeiro: jq -e '.feature_flags.new_checkout' config.json.Formatar JSON de Arquivos e Respostas de API
Duas fontes comuns de JSON em scripts de shell são arquivos em disco e respostas HTTP de API via curl. Cada uma tem um padrão de tratamento ligeiramente diferente. Para arquivos, a principal preocupação é a edição segura no lugar. Para respostas de API, o detalhe-chave é suprimir a barra de progresso do curl para que ela não corrompa o input do jq.
Formatação segura no lugar de um arquivo
# Formatar e sobrescrever com segurança usando um arquivo temporário tmp=$(mktemp) jq --indent 2 . config/feature-flags.json > "$tmp" && mv "$tmp" config/feature-flags.json echo "Formatado config/feature-flags.json"
Formatar uma resposta de API com curl
# Formatar o status de deploy da API DEPLOY_ID="dep_8f3a2b9c" curl -s \ -H "Authorization: Bearer $DEPLOY_API_TOKEN" \ "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \ | jq --indent 2 .
Formatar e filtrar simultaneamente
# Obter formatado + filtrar somente erros de um endpoint de monitoramento
curl -s "https://monitoring.internal/api/events?level=error&limit=10" \
| jq '[.events[] | {id, message, timestamp, service}]' \
|| { echo "Falha ao buscar ou analisar eventos" >&2; exit 1; }O padrão || { ... } é crítico aqui. Sem ele, uma falha no curl ou uma resposta de API malformada passa silenciosamente e a próxima etapa do script opera com dados vazios ou parciais. Se você precisa inspecionar respostas aninhadas complexas sem escrever uma expressão de filtro primeiro, o Formatador JSON baseado no navegador permite colar a resposta bruta e navegar pela árvore interativamente.
Formatar JSON em Pipelines CI/CD
CI é onde as portas de validação de JSON mais importam — uma configuração malformada que chega à produção é muito mais dolorosa de reverter do que uma falha no pipeline. A maioria dos concorrentes documenta o jq para uso pontual no terminal; os padrões abaixo são os que uso em fluxos de trabalho SRE em produção para detectar erros de configuração antes que cheguem a um slot de deployment.
GitHub Actions — validar todas as configurações JSON
- name: Validar configurações JSON
run: |
echo "Validando arquivos de configuração JSON..."
find . -name "*.json" -not -path "*/node_modules/*" | while read -r f; do
if ! jq . "$f" > /dev/null 2>&1; then
echo "::error file=$f::Sintaxe JSON inválida"
exit 1
fi
done
echo "Todos os arquivos JSON são válidos"Hook pre-commit — validar arquivos JSON em staging
#!/usr/bin/env bash
set -euo pipefail
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep '\.json$' || true)
[ -z "$STAGED" ] && exit 0
for f in $STAGED; do
jq . "$f" > /dev/null 2>&1 || { echo "JSON inválido: $f"; exit 1; }
done
echo "Validação JSON aprovada"scripts/validate-json.sh, torne-o executável com chmod +x scripts/validate-json.sh, depois crie um symlink: ln -s ../../scripts/validate-json.sh .git/hooks/pre-commit.Formatar Variáveis JSON e Heredocs em Bash
Scripts de shell frequentemente constroem payloads JSON dinamicamente — a partir de variáveis de ambiente, metadados do git ou valores calculados. O padrão mais seguro é jq -n --arg / --argjson em vez de interpolação de strings, que quebra no momento em que um valor contém aspas ou uma quebra de linha. Sempre coloque variáveis entre aspas duplas ao redirecionar para o jq para evitar divisão de palavras em espaços em branco no JSON.
Formatar uma variável com resposta de API armazenada
# Sempre coloque "$API_RESPONSE" entre aspas — espaços no JSON quebrariam uma expansão sem aspas echo "$API_RESPONSE" | jq --indent 2 .
Construir e formatar um payload com jq -n
payload=$(jq -n \
--arg env "production" \
--arg version "$(git describe --tags)" \
--argjson replicas 3 \
'{environment: $env, version: $version, replicas: $replicas}')
# Inspecionar o payload construído
echo "$payload" | jq .
# Enviá-lo para uma API
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DEPLOY_API_TOKEN" \
-d "$payload" \
"https://api.deployments.internal/v1/deploys"--arg sempre vincula um valor de string. --argjson analisa o valor como JSON primeiro, então você pode passar números, booleanos, arrays e objetos sem colocá-los entre aspas na expressão de filtro.Formatar JSON em Bash Sem Instalar o jq
Quando o jq não está disponível — imagens Docker mínimas, runners de CI restritos ou sistemas onde você não pode instalar pacotes — o módulo json.tool integrado do Python oferece a mesma capacidade central. Ele faz parte da biblioteca padrão do Python; se o Python 3 estiver instalado, funciona sem dependências adicionais.
# Formatar a partir de um arquivo python3 -m json.tool config.json # Controlar a largura da indentação python3 -m json.tool --indent 2 config.json # Ordenar chaves alfabeticamente python3 -m json.tool --sort-keys config.json # Formatar a partir do stdin (ex.: redirecionado do curl) curl -s https://api.deployments.internal/v1/status | python3 -m json.tool
python3 -m json.tool é mais estrito que o jq: rejeita vírgulas finais, comentários e extensões JSON5. Essa rigidez é desejável para validação de configurações em produção, mas pode ser um ponto de fricção ao trabalhar com JSON laxo de ferramentas de terceiros. Também não produz saída colorida, tornando a inspeção no terminal menos ergonômica do que o jq para uso interativo.# Validação com código de saída (mesma semântica do jq)
python3 -m json.tool config.json > /dev/null && echo "válido" || echo "inválido"
# Validação de string inline
echo '{"service":"payments-api","healthy":true}' | python3 -m json.tool > /dev/null
echo "Código de saída: $?" # 0 = válidoSaída no Terminal com Realce de Sintaxe
jq coloriza sua saída por padrão — chaves em azul, strings em verde, números em branco. Quando você precisa de realce de sintaxe JSON completo em um paginador com rolagem, ou ao depurar respostas grandes e aninhadas em uma sessão de terminal, bat oferece a experiência mais ergonômica. Ambos são úteis para depuração e inspeção interativa; nenhum deve ser usado ao gravar saída em arquivos ou respostas de API.
Instalar o bat
# macOS brew install bat # Debian / Ubuntu (o binário pode se chamar batcat — crie um alias se necessário) apt-get install -y bat # alias bat=batcat # adicionar ao ~/.bashrc se necessário # Verificar bat --version # bat 0.24.0
Visualizar arquivos JSON com realce de sintaxe
# JSON com realce de sintaxe no paginador (pressione q para sair) bat config/app-config.json # Desativar o paginador — exibir diretamente no terminal bat --paging=never config/app-config.json # Redirecionar a saída do jq pelo bat para inspeção colorida jq '.database' infra/app-config.json | bat --language=json --paging=never
Saída do jq colorida em um paginador com rolagem
# -C força a cor mesmo quando stdout não é um tty (ex.: ao redirecionar para less) jq -C . logs/deploy-response.json | less -R
bat / jq -C) apenas para inspeção e depuração no terminal. Remova códigos de cor ANSI antes de gravar em arquivos de log ou redirecionar para outras ferramentas — use jq -M . (--monochrome-output) ou bat --plain.Trabalhando com Arquivos JSON Grandes em Bash
Quando um arquivo JSON ultrapassa 50–100 MB, carregá-lo na memória com o modo padrão do jq pode ser lento ou desencadear OOM em hosts com memória limitada (contêineres Docker com limite de 512 MB, por exemplo). jq --stream emite pares caminho/valor incrementalmente à medida que lê, sem armazenar o documento inteiro em buffer. Para NDJSON (um objeto JSON por linha), o jq tem uma abordagem nativa mais eficiente.
Transmitir um arquivo JSON grande com jq --stream
# --stream emite pares [caminho, escalar] à medida que o jq lê o input # Extrair todos os campos "status" de um grande arquivo de log sem carregá-lo completamente jq -c --stream 'if length == 2 and (.[0][-1] == "status") then .[1] else empty end' logs/archive-2026-03.json
NDJSON / JSON Lines — processar um objeto por linha
# NDJSON: um objeto JSON por linha — comum em exportações do Kafka, Fluentd e Logstash
# -R lê linhas brutas; fromjson? ignora linhas que não são JSON válido
jq -c -R 'fromjson? | {id: .request_id, status: .http_status, latency: .duration_ms}' logs/access-2026-03-13.ndjson > logs/summary.ndjson# Alternativa com loop shell — útil quando você precisa de tratamento de erros por linha
while IFS= read -r line; do
echo "$line" | jq -c '{id: .request_id, status: .http_status}' 2>/dev/null || echo "PULAR: linha malformada" >&2
done < logs/access-2026-03-13.ndjsonjq . file.json padrão para --stream quando o arquivo for maior que 50–100 MB ou quando o processo rodar dentro de um contêiner com limite de memória. Para pipelines NDJSON, prefira jq -R 'fromjson?' a um loop while read de shell — é significativamente mais rápido porque evita criar um subshell por linha.Erros Comuns
Problema: O shell abre e trunca o arquivo de saída antes que o jq leia o input. Se origem e destino forem o mesmo caminho, o jq lê um arquivo vazio.
Solução: Escreva primeiro em um arquivo temporário mktemp, depois substitua o original atomicamente com mv.
jq --indent 2 . settings.json > settings.json
tmp=$(mktemp) && jq --indent 2 . settings.json > "$tmp" && mv "$tmp" settings.json
Problema: Sem um tratador de erros, o script continua silenciosamente com um arquivo formatado vazio ou ausente quando o JSON é inválido — etapas posteriores falham então com erros confusos.
Solução: Adicione || { echo '...' >&2; exit 1; } após cada chamada ao jq que produza saída usada por uma etapa posterior.
jq . response.json > formatted.json
jq . response.json > formatted.json || { echo "JSON inválido em response.json" >&2; exit 1; }Problema: O curl imprime uma barra de progresso no stderr por padrão. Quando o stderr é mesclado com o stdout (ex.: em subshells ou captura de logs), o texto da barra de progresso aparece no input do jq e causa um erro de análise.
Solução: Sempre passe -s (silencioso) ao curl ao redirecionar para o jq. Use -v ou --fail-with-body separadamente se precisar de saída de diagnóstico.
curl https://api.payments.internal/config | jq .
curl -s https://api.payments.internal/config | jq .
Problema: O flag -r / --raw-output remove aspas JSON de valores de string de nível superior — não formata objetos ou arrays. Passar -r . a um objeto produz o mesmo objeto compacto, não saída indentada.
Solução: Use jq . (sem o flag -r) para formatar. Reserve -r para extrair valores de string puros como jq -r '.version' config.json.
jq -r . config.json
jq . config.json
jq vs python3 vs json_pp — Comparação Rápida
A escolha entre ferramentas depende do que está disponível no seu ambiente e do que você precisa além da formatação básica:
Para a maioria dos trabalhos de scripting bash e CI/CD, o jq é o padrão correto — valida, formata, filtra e fornece códigos de saída confiáveis em um único binário sem dependência de runtime. Recorra ao python3 -m json.tool quando não puder instalar pacotes adicionais e o Python já estiver presente.
Perguntas Frequentes
Como formatar um arquivo JSON no lugar usando bash?
Nunca redirecione a saída do jq de volta ao mesmo arquivo — o shell trunca o arquivo antes que o jq o leia. Em vez disso, escreva primeiro em um arquivo temporário e substitua o original atomicamente com mv.
tmp=$(mktemp) jq --indent 2 . config/app-config.json > "$tmp" && mv "$tmp" config/app-config.json echo "Formatado no lugar com sucesso"
Como validar JSON em um script bash e sair em caso de erro?
Passe o arquivo ao jq e redirecione stdout para /dev/null. Use || para capturar a saída não-zero e abortar o script. O jq sai com código 1 em qualquer erro de análise, tornando-o confiável como porta de validação em CI.
validate_json() {
local file="$1"
if jq . "$file" > /dev/null 2>&1; then
echo "✓ JSON válido: $file"
return 0
else
echo "✗ JSON inválido: $file" >&2
return 1
fi
}
validate_json infra/k8s/app-config.json || exit 1Como formatar JSON em bash sem instalar o jq?
Use o módulo json.tool integrado do python3 — ele vem com toda instalação padrão do Python e produz saída corretamente indentada com a mesma semântica de código de saída do jq.
# Formatar a partir de um arquivo python3 -m json.tool config.json # Formatar a partir do stdin (ex.: uma resposta curl) curl -s https://api.internal/status | python3 -m json.tool --indent 2
Como formatar JSON a partir de uma resposta curl em bash?
Sempre passe -s (silencioso) ao curl para que barras de progresso não corrompam o input do jq. Redirecione o stdout do curl diretamente para o jq.
DEPLOY_ID="dep_8f3a2b9c" curl -s \ -H "Authorization: Bearer $DEPLOY_API_TOKEN" \ "https://api.deployments.internal/v1/deploys/$DEPLOY_ID" \ | jq --indent 2 .
Como formatar apenas parte de um arquivo JSON usando jq?
Use uma expressão de caminho jq em vez do filtro de identidade (.) para extrair e formatar um objeto ou array aninhado. O resultado é ele próprio um JSON formatado.
# Formatar apenas o bloco de configuração do banco de dados
jq --indent 2 '.database' infra/app-config.json
# Formatar + filtrar o array de eventos somente para o nível de erro
jq '[.events[] | select(.level == "error") | {id, message, service}]' events.jsonQual código de saída o jq retorna para JSON inválido?
O jq sai com código 1 para qualquer erro de análise e também quando o flag -e / --exit-status está ativo e a saída é false ou null. O código de saída 0 significa que JSON válido foi analisado e produziu saída verdadeira. O código de saída 5 indica um erro de uso.
# Testar o código de saída diretamente
echo '{"ok":true}' | jq . > /dev/null 2>&1; echo "saída: $?" # saída: 0
echo '{json ruim}' | jq . > /dev/null 2>&1; echo "saída: $?" # saída: 1
# flag -e: sai 1 se a saída for false/null
echo 'null' | jq -e . > /dev/null 2>&1; echo "saída: $?" # saída: 1Ferramentas Relacionadas
Alternativas e complementos baseados no navegador para formatação JSON em bash — úteis quando você precisa de uma interface visual, um link compartilhável ou está trabalhando fora de um terminal:
Nadia is a site reliability engineer who lives in the terminal. She writes Bash scripts that process logs, transform data, and orchestrate infrastructure across fleets of servers. She is a heavy user of jq, awk, and sed and writes about shell one-liners, text processing pipelines, data serialisation from the command line, and the practical Bash patterns that SREs reach for when speed matters more than elegance.
Erik is a DevOps engineer who has spent years writing and maintaining the shell scripts that hold CI/CD pipelines together. He writes about Bash best practices, portable POSIX shell, encoding and decoding in shell scripts, secret management from the command line, and the patterns that separate reliable automation scripts from brittle ones. He is a strong believer in making shell scripts readable and testable with tools like bats-core.