Formatar JSON em Bash com jq — Guia e Validação

·SRE & Shell Scripting Specialist·Revisado porErik Lindqvist·Publicado

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.

PONTOS-CHAVE
  • jq . formata E valida simultaneamente — sai com código 1 em JSON inválido
  • • Use jq -e em 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.tool funciona 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.

Before · json
After · json
{"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

Bash
# 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

Bash
# 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.json

Gravar a saída formatada em um arquivo

Bash
# 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
Nota: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

Bash
# 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:

Opção
Tipo
Padrão
Descrição
.
filtro
Filtro de identidade — formata e exibe o input completo sem alterações.
--indent N
int
2
Define a indentação como N espaços (0–7). Use 2 ou 4 para formatação padrão.
--tab
flag
off
Indenta com um caractere de tabulação em vez de espaços.
-c / --compact-output
flag
off
Colapsa a saída em uma única linha (minifica). Desfaz o pretty-print.
-r / --raw-output
flag
off
Exibe strings sem aspas JSON. Útil para extrair valores de texto puro.
-e / --exit-status
flag
off
Sai com código 1 se a saída for false ou null. Ideal para asserções em CI.
-M / --monochrome-output
flag
off
Desativa saída colorida — útil ao redirecionar para arquivos ou destinos não terminais.
-S / --sort-keys
flag
off
Ordena todas as chaves de objetos alfabeticamente em cada nível de aninhamento.
-n / --null-input
flag
off
Não lê input; use com --arg / --argjson para construir JSON do zero.
--arg name val
string
Vincula uma string do shell como variável jq nomeada ($name) acessível no filtro.

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

Bash
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

Bash
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

Bash
find ./config -name "*.json" | while read -r f; do
  jq . "$f" > /dev/null 2>&1 || echo "INVÁLIDO: $f"
done
Nota:O flag -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

Bash
# 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

Bash
# 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

Bash
# 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

YAML
- 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

Bash
#!/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"
Nota:Salve o hook pre-commit em 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

Bash
# 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

Bash
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"
Nota:--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.

Bash
# 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
Aviso: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.
Bash
# 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álido

Saí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

Bash
# 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

Bash
# 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

Bash
# -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
Aviso:Use saída colorida (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

Bash
# --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

Bash
# 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
Bash
# 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.ndjson
Nota:Mude de jq . 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

Sobrescrever o arquivo fonte com redirecionamento shell

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.

Before · Bash
After · Bash
jq --indent 2 . settings.json > settings.json
tmp=$(mktemp) && jq --indent 2 . settings.json > "$tmp" && mv "$tmp" settings.json
Não tratar falhas do jq em scripts

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.

Before · Bash
After · Bash
jq . response.json > formatted.json
jq . response.json > formatted.json || { echo "JSON inválido em response.json" >&2; exit 1; }
Esquecer -s com curl

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.

Before · Bash
After · Bash
curl https://api.payments.internal/config | jq .
curl -s https://api.payments.internal/config | jq .
Usar jq -r . esperando JSON formatado

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.

Before · Bash
After · Bash
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:

Tool
Valida
Coloriza
Apto para CI
Códigos de saída
Controle de indentação
Install
jq
✅ (código 1)
✅ --indent N
brew / apt / dnf
python3 -m json.tool
✅ (estrito)
✅ (código 1)
✅ --indent N
Incluso (Python)
json_pp (Perl)
⚠️ parcial
⚠️ variável
Incluso (Perl)
fx (Node.js)
⚠️ parcial
⚠️ limitado
npm install -g fx
node -e JSON.parse
✅ JSON.stringify
Incluso (Node.js)

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.

Bash
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.

Bash
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 1

Como 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.

Bash
# 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.

Bash
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.

Bash
# 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.json

Qual 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.

Bash
# 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: 1

Ferramentas 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:

Também disponível em:PythonGoJavaScript
NO
Nadia OkonkwoSRE & Shell Scripting Specialist

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.

EL
Erik LindqvistRevisor técnico

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.