JSON Formatter Python — Guia do json.dumps()
Use o Formatador e Embelezador JSON gratuito diretamente no seu navegador — sem instalação.
Experimentar Formatador e Embelezador JSON online →Quando depuro um cliente de API em Python, o primeiro recurso que busco é formatar json em python — uma única chamada a json.dumps(data, indent=4) transforma um blob ilegível em uma string perfeitamente navegável. O módulo integrado json do Python resolve isso completamente na biblioteca padrão — sem instalação de terceiros. Se precisar apenas de um resultado rápido sem escrever código, o Formatador JSON do ToolDeck faz isso instantaneamente. Este guia cobre todos os métodos práticos: json.dumps() com todos os seus parâmetros, pprint, orjson para formatação de alto desempenho, a CLI json.tool, serialização de tipos personalizados como datetime e UUID, processamento de arquivos de gigabytes com ijson, e destaque de sintaxe no terminal com rich — tudo com código compatível com Python 3.8+.
- →
json.dumps(data, indent=4)está integrado na stdlib do Python desde a versão 2.6 — sem instalação. - →Passe
ensure_ascii=Falsesempre que seus dados contiverem letras acentuadas, caracteres CJK ou emojis. - →Para
datetime,UUIDou classes personalizadas, use o parâmetrodefault=ou crie uma subclasse dejson.JSONEncoder. - →
separators=(',', ':')elimina todos os espaços — use para transmissão em rede ou embedding em URLs. - →
orjsoné 5–10× mais rápido que a stdlib e gerenciadatetimeeuuid.UUIDde forma nativa. - →
pprint.pprint()produz sintaxe Python (True/None), não JSON válido — nunca use para arquivos ou respostas de API. - →Para arquivos JSON maiores que 50 MB, use streaming com
ijsonem vez dejson.load()para evitarMemoryError.
O que é a formatação JSON?
A formatação legível (pretty printing) transforma uma string JSON densa e minificada em um formato legível com indentação consistente e quebras de linha. A transformação é puramente cosmética: os dados são idênticos, apenas a apresentação muda. O módulo json do Python resolve isso inteiramente na biblioteca padrão — nada a instalar.
{"id":"usr_j8s3p2","nome":"João Silva","cargos":["admin","editor"],"config":{"tema":"escuro","idioma":"pt"}}{
"id": "usr_j8s3p2",
"nome": "João Silva",
"cargos": [
"admin",
"editor"
],
"config": {
"tema": "escuro",
"idioma": "pt"
}
}json.dumps() — A forma padrão de formatar JSON
json.dumps() faz parte da biblioteca padrão do Python desde a versão 2.6 — basta import json, sem instalação adicional. Serializa qualquer objeto Python compatível com JSON em uma string formatada. O parâmetro-chave é indent: defina como 4 (ou 2) para obter uma saída legível.
import json
usuario = {
"id": "usr_j8s3p2",
"nome": "João Silva",
"cargos": ["admin", "editor"],
"config": {"tema": "escuro", "idioma": "pt"}
}
print(json.dumps(usuario, indent=4, ensure_ascii=False))
# Saída:
# {
# "id": "usr_j8s3p2",
# "nome": "João Silva",
# "cargos": [
# "admin",
# "editor"
# ],
# "config": {
# "tema": "escuro",
# "idioma": "pt"
# }
# }Para uso em produção, geralmente você vai querer sort_keys=True (saída consistente entre execuções) e ensure_ascii=False (preservar acentos do português):
import json
resposta_api = {
"timestamp": "2024-05-01T10:30:00Z",
"status": "sucesso",
"dados": {
"user_id": "usr_j8s3p2",
"nome_completo": "Camila Rocha",
"cidade": "São Paulo",
"pontuacao": 4892.5,
"tags": ["python", "backend", "api"]
}
}
print(json.dumps(resposta_api, indent=4, sort_keys=True, ensure_ascii=False))
# Saída (chaves ordenadas, acentos preservados):
# {
# "dados": {
# "cidade": "São Paulo",
# "nome_completo": "Camila Rocha",
# "pontuacao": 4892.5,
# "tags": ["api", "backend", "python"],
# "user_id": "usr_j8s3p2"
# },
# "status": "sucesso",
# "timestamp": "2024-05-01T10:30:00Z"
# }json.dumps() retorna uma string. Para escrever JSON formatado diretamente em um arquivo, use json.dump(data, f, indent=4) (sem o s) — escreve no objeto arquivo e evita criar uma string intermediária em memória.Referência de parâmetros do json.dumps()
Todos os parâmetros são opcionais, exceto o objeto em si. Os valores padrão produzem JSON compacto e seguro em ASCII — passe os parâmetros explicitamente para obter uma saída legível por humanos.
Saída JSON compacta com o parâmetro separators
Por padrão, json.dumps() separa os itens com ", " e as chaves dos valores com ": ". O parâmetro separators permite sobrescrever ambos. Passar (',', ':') elimina todos os espaços e produz o JSON válido mais compacto possível — útil para transmissão em rede, embedding em URLs ou armazenamento em colunas de banco de dados.
import json
payload = {
"endpoint": "/api/v2/eventos",
"filtros": {"status": "ativo", "limite": 100},
"ordem": "desc"
}
# Padrão — espaços após separadores (legível)
saida_normal = json.dumps(payload, ensure_ascii=False)
# {"endpoint": "/api/v2/eventos", "filtros": {"status": "ativo", "limite": 100}, "ordem": "desc"}
# len = 88
# Compacto — sem espaços
saida_compacta = json.dumps(payload, separators=(',', ':'), ensure_ascii=False)
# {"endpoint":"/api/v2/eventos","filtros":{"status":"ativo","limite":100},"ordem":"desc"}
# len = 80 (9% menor; a economia cresce com payloads maiores)
# Compacto + chaves ordenadas para hashes reproduzíveis
canonico = json.dumps(payload, separators=(',', ':'), sort_keys=True, ensure_ascii=False)
print(canonico)
# {"endpoint":"/api/v2/eventos","filtros":{"limite":100,"status":"ativo"},"ordem":"desc"}indent= junto com separators=, o argumento separators controla apenas os separadores inline — as quebras de linha e a indentação de indent são preservadas. Se quiser uma saída compacta em uma única linha, omita indent (ou passe None) e defina separators=(',', ':').Serialização de objetos Python personalizados com o parâmetro default
O módulo padrão json serializa dicts, listas, strings, números, booleanos e None — mas lança um TypeError para qualquer outro tipo. Os dois culpados mais comuns em código de produção são os objetos datetime e os UUID.
import json
from datetime import datetime, timezone
import uuid
pedido = {
"pedido_id": uuid.uuid4(), # ❌ TypeError: UUID is not JSON serializable
"criado_em": datetime.now(timezone.utc), # ❌ TypeError: datetime is not JSON serializable
"total_brl": 142.50,
"itens": ["assinatura-pro", "addon-armazenamento"]
}
json.dumps(pedido) # lança TypeErrorAbordagem 1 — o parâmetro default=
Passe um callable para o parâmetro default=. json.dumps() o chama para qualquer objeto que não saiba tratar. Retorne uma representação serializável, ou lance TypeError para tipos que não suportar explicitamente — nunca ignore tipos desconhecidos em silêncio.
import json
from datetime import datetime, timezone, date
import uuid
from decimal import Decimal
def json_padrao(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, Decimal):
return float(obj)
raise TypeError(f"O tipo {type(obj).__name__!r} não é serializável em JSON")
pedido = {
"pedido_id": uuid.uuid4(),
"criado_em": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
"total_brl": Decimal("142.50"),
"itens": ["assinatura-pro", "addon-armazenamento"]
}
print(json.dumps(pedido, indent=4, default=json_padrao, ensure_ascii=False))
# {
# "pedido_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
# "criado_em": "2024-05-01T10:30:00+00:00",
# "total_brl": 142.5,
# "itens": ["assinatura-pro", "addon-armazenamento"]
# }Abordagem 2 — subclasse de json.JSONEncoder
Para lógica de codificação reutilizável compartilhada entre vários módulos, criar uma subclasse de json.JSONEncoder é mais limpo do que passar uma função default por todos os lugares. Sobrescreva o método default e chame super().default(obj) como último recurso — isso preserva o comportamento correto de erro para tipos não suportados.
import json
from datetime import datetime, timezone
import uuid
from decimal import Decimal
class AppEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, Decimal):
return float(obj)
return super().default(obj) # lança TypeError para tipos desconhecidos
pedido = {
"pedido_id": uuid.uuid4(),
"criado_em": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
"total_brl": Decimal("142.50"),
}
# Passe a classe encoder com cls=
print(json.dumps(pedido, indent=4, cls=AppEncoder, ensure_ascii=False))
# Saída idêntica à abordagem com default=super().default(obj) (ou lance TypeError explicitamente) para tipos não reconhecidos. Retornar silenciosamente str(obj) para tudo vai corromper objetos que deveriam ter lançado um erro — um bug difícil de rastrear em produção.Decodificando de volta — object_hook
Codificar é apenas metade do processo. Para reconstruir um objeto Python personalizado a partir do JSON, passe uma função object_hook para json.loads() ou json.load(). O hook é chamado para cada objeto JSON decodificado (dict) e pode retornar qualquer valor Python — permitindo um ciclo completo de codificação ↔ decodificação.
import json
from datetime import datetime
from dataclasses import dataclass
@dataclass
class Evento:
nome: str
ocorrido_em: datetime
user_id: str
def codificar_evento(obj):
if isinstance(obj, Evento):
return {
"__tipo__": "Evento",
"nome": obj.nome,
"ocorrido_em": obj.ocorrido_em.isoformat(),
"user_id": obj.user_id,
}
raise TypeError(f"Não é possível serializar {type(obj)}")
def decodificar_evento(d):
if d.get("__tipo__") == "Evento":
return Evento(
nome=d["nome"],
ocorrido_em=datetime.fromisoformat(d["ocorrido_em"]),
user_id=d["user_id"],
)
return d
# Codificar
evento = Evento("login", datetime(2024, 5, 1, 10, 30), "usr_j8s3p2")
json_str = json.dumps(evento, default=codificar_evento, indent=4)
# Decodificar de volta para uma instância de Evento
restaurado = json.loads(json_str, object_hook=decodificar_evento)
print(type(restaurado)) # <class 'Evento'>
print(restaurado.ocorrido_em) # 2024-05-01 10:30:00object_hook é chamado para cada dict aninhado no documento — não apenas o de nível superior. Inclua um campo discriminador (como "__tipo__") para que o hook possa distinguir seus objetos personalizados de dicts simples que devem permanecer como estão.pprint — O módulo alternativo (e quando não usá-lo)
O módulo pprint do Python (pretty printer) formata estruturas de dados Python para legibilidade no terminal. Ele opera sobre objetos Python parseados, não sobre strings JSON — e sua saída usa sintaxe Python, não sintaxe JSON.
import json, pprint
raw = '{"sensor_id":"s-441","leituras":[23.1,23.4,22.9],"unidade":"celsius","ativo":true}'
data = json.loads(raw)
# pprint — repr Python válido, NÃO JSON válido
pprint.pprint(data, sort_dicts=False)
# {'sensor_id': 's-441',
# 'leituras': [23.1, 23.4, 22.9],
# 'unidade': 'celsius',
# 'ativo': True} ← Python True, não JSON true
# json.dumps — JSON válido
print(json.dumps(data, indent=4, ensure_ascii=False))
# {
# "sensor_id": "s-441",
# "leituras": [23.1, 23.4, 22.9],
# "unidade": "celsius",
# "ativo": true ← JSON válido
# }pprint para um endpoint de API nem a escreva em um arquivo .json — vai quebrar qualquer parser JSON que espere sintaxe padrão. Use json.dumps(indent=4) para toda saída que precise ser JSON válido.Quando faz sentido usar pprint: inspeção rápida no REPL ou em logs de depuração, especialmente quando o objeto contém tipos não serializáveis em JSON (sets, instâncias de classes, dataclasses antes da conversão).
Como formatar uma resposta JSON do Requests
O cenário mais comum no mundo real: você tem um arquivo JSON em disco ou uma resposta HTTP de uma API e quer formatá-lo para depuração ou logging. Ambos os casos usam a mesma abordagem — fazer o parse para um dict Python e depois formatar com json.dumps().
Lendo de um arquivo
import json
try:
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
# Imprimir no console com formatação
print(json.dumps(data, indent=4, ensure_ascii=False))
# Ou gravar a versão formatada de volta no disco
with open("config.formatado.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
except json.JSONDecodeError as e:
print(f"JSON inválido: {e}")
except FileNotFoundError:
print(f"Arquivo não encontrado: config.json")Formatando uma resposta de API
import json, requests
from requests.exceptions import HTTPError, ConnectionError, Timeout
def imprimir_api(url: str) -> None:
try:
resp = requests.get(url, timeout=10)
resp.raise_for_status()
print(json.dumps(resp.json(), indent=4, ensure_ascii=False))
except HTTPError as e:
print(f"HTTP {e.response.status_code}: {e}")
except (ConnectionError, Timeout) as e:
print(f"Erro de rede: {e}")
except json.JSONDecodeError:
print(f"O corpo da resposta não é JSON:\n{resp.text[:500]}")
imprimir_api("https://api.github.com/repos/python/cpython")response.json() já faz o parse do corpo da resposta — não é necessário chamar json.loads() separadamente. Sempre adicione raise_for_status() antes de acessar .json() para capturar erros 4xx/5xx antes que causem um confuso erro de parse.Formatação pela linha de comando
O Python inclui json.tool, um módulo CLI para formatar JSON diretamente do terminal — sem necessidade de escrever código Python. Está disponível em qualquer máquina com Python instalado.
# Formatar um arquivo local
python -m json.tool config.json
# Canalizar resposta de API pelo formatador
curl -s https://api.github.com/users/gvanrossum | python -m json.tool
# Formatar do stdin
echo '{"servico":"api-gateway","versao":"2.1.0","saudavel":true}' | python -m json.tool
# Ordenar chaves alfabeticamente
python -m json.tool --sort-keys data.json
# Indentação personalizada (Python 3.9+)
python -m json.tool --indent 2 data.json--indent e --no-indent. Para filtragem JSON mais poderosa no terminal, considere jq — mas python -m json.tool cobre o caso de uso de formatação sem dependências adicionais.Se não estiver num terminal de todo — colando uma resposta do Postman ou um arquivo de log — o Formatador JSON do ToolDeck permite colar, formatar e copiar num único passo com realce de sintaxe e validação integrados.
Bibliotecas alternativas: orjson e rich
orjson — 5–10× mais rápido com suporte nativo de tipos
O módulo padrão json é suficientemente rápido para a maioria dos casos de uso, mas se você serializa milhares de objetos por segundo — pipelines de logging, APIs de alto throughput, exportações em massa de dados — orjson é 5–10× mais rápido. Também gerencia nativamente tipos que a biblioteca padrão não consegue serializar sem uma função default personalizada: datetime, uuid.UUID, arrays numpy e dataclasses.
pip install orjson
import orjson
from datetime import datetime, timezone
import uuid
evento = {
"evento_id": uuid.uuid4(), # sem str() — orjson trata UUID
"timestamp": datetime.now(timezone.utc), # sem isoformat()
"servico": "auth-service",
"nivel": "INFO",
"payload": {
"user_id": "usr_j8s3p2",
"acao": "login",
"ip": "192.168.1.42",
"latencia_ms": 34
}
}
# orjson.dumps retorna bytes; .decode() converte para str
print(orjson.dumps(evento, option=orjson.OPT_INDENT_2).decode())
# {
# "evento_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
# "timestamp": "2024-05-01T10:30:00+00:00",
# "servico": "auth-service",
# ...
# }Duas coisas a saber: orjson.dumps() retorna bytes, não uma string — chame .decode() se precisar de uma string. Suporta apenas indentação de 2 espaços via OPT_INDENT_2; para saída com 4 espaços use o padrão json.dumps(indent=4).
rich — Destaque de sintaxe no terminal
Se você inspeciona JSON regularmente no terminal ou em um REPL, rich renderiza uma saída colorida com destaque de sintaxe que torna estruturas profundamente aninhadas legíveis em um instante. Chaves, strings, números e booleanos têm cada um uma cor diferente — muito mais fácil de escanear do que uma parede de texto monocromático. É uma ferramenta apenas para depuração, não para serialização em produção.
pip install rich
from rich import print_json
import json
# print_json() aceita uma string JSON
raw = '{"evento":"login","user_id":"usr_j8s3p2","timestamp":"2024-05-01T10:30:00Z","sucesso":true,"meta":{"ip":"192.168.1.42","tentativas":1}}'
print_json(raw)
# Para formatar um dict Python, converta-o primeiro para string
dados = {
"status": "sucesso",
"total": 42,
"tags": ["python", "api", "backend"]
}
print_json(json.dumps(dados, ensure_ascii=False))rich.print_json() emite códigos de escape ANSI para a cor do terminal — nunca capture esta saída e a escreva em um arquivo .json nem a envie como resposta de API. Use json.dumps(indent=4) para qualquer saída legível por máquinas.simplejson — Substituto compatível com a stdlib
simplejson é a biblioteca que se tornou o módulo json do Python — é mantida de forma independente e fica à frente da stdlib em funcionalidades menores. É um substituto direto: troque o import e o restante do código permanece inalterado. Útil quando você precisa de suporte a Decimal sem um encoder personalizado, ou quando o ambiente Python é mais antigo.
pip install simplejson
import simplejson as json # API idêntica à stdlib
from decimal import Decimal
pedido = {
"item": "Assinatura API Lisboa",
"preco": Decimal("49.99"), # stdlib json lançaria TypeError aqui
"quantidade": 3,
}
# simplejson serializa Decimal nativamente — sem default= necessário
print(json.dumps(pedido, indent=4, use_decimal=True, ensure_ascii=False))
# {
# "item": "Assinatura API Lisboa",
# "preco": 49.99,
# "quantidade": 3
# }orjson é a melhor opção. Use simplejson quando precisar de serialização nativa de Decimal sem escrever um encoder personalizado, ou quando mantiver uma base de código que já o utiliza.Processando arquivos JSON grandes sem ficar sem memória
json.load() lê o arquivo inteiro na memória antes que você possa acessar um único campo. Em um arquivo com milhões de registros ou um payload acima de um gigabyte, isso causa um MemoryError — ou na melhor das hipóteses força o processo a usar swap e funcionar muito lentamente.
Streaming com ijson
ijson é um parser JSON de streaming que gera itens um a um a partir de um objeto arquivo. Você itera sobre os elementos do array sem nunca carregar o dataset completo na memória — o pico de uso de memória é proporcional a um único objeto, não ao tamanho do arquivo.
pip install ijson
import ijson
from decimal import Decimal
# eventos.json tem estrutura: {"eventos": [...milhões de objetos...]}
receita_total = Decimal("0")
contagem_logins = 0
with open("eventos.json", "rb") as f: # ijson requer modo binário
for evento in ijson.items(f, "eventos.item"):
if evento.get("tipo") == "compra":
receita_total += Decimal(str(evento["valor_brl"]))
elif evento.get("tipo") == "login":
contagem_logins += 1
print(f"Receita: R${receita_total:.2f} | Logins: {contagem_logins}")
# Processa um arquivo de 2 GB com ~30 MB de pico de uso de memóriajson.load() para ijson quando seu arquivo ultrapassar aproximadamente 50–100 MB. Abaixo desse limite, json.load() é mais simples e significativamente mais rápido por usar um parser em C internamente. Acima de 100 MB, a economia de memória do streaming compensa o custo adicional.NDJSON — um objeto JSON por linha
NDJSON (JSON delimitado por nova linha, também chamado JSON Lines ou .jsonl) armazena um objeto JSON completo por linha. Exportadores de logs, consumidores do Kafka e pipelines de dados frequentemente produzem esse formato porque cada linha pode ser adicionada e lida de forma independente. A biblioteca padrão o trata sem dependências adicionais.
import json
# Escrever NDJSON — um evento por linha
eventos = [
{"ts": "2024-05-01T10:00:00Z", "usuario": "usr_j8s3p2", "acao": "login"},
{"ts": "2024-05-01T10:01:03Z", "usuario": "usr_j8s3p2", "acao": "compra", "sku": "plano-pro"},
{"ts": "2024-05-01T10:15:42Z", "usuario": "usr_4ab1d9", "acao": "login"},
]
with open("eventos.ndjson", "w", encoding="utf-8") as f:
for evento in eventos:
f.write(json.dumps(evento, ensure_ascii=False) + "\n")
# Ler NDJSON — memória constante, independente do tamanho do arquivo
contagem_compras = 0
with open("eventos.ndjson", "r", encoding="utf-8") as f:
for linha in f:
linha = linha.strip()
if not linha: # pular linhas em branco
continue
evento = json.loads(linha)
if evento.get("acao") == "compra":
contagem_compras += 1
print(f"{evento['ts']} — {evento['usuario']} comprou {evento['sku']}")Erros Comuns
Já vi esses quatro erros em quase todas as revisões de código que envolvem serialização JSON — especialmente em desenvolvedores vindos do JavaScript, onde JSON.stringify gerencia a codificação automaticamente.
Problema: print() sobre um dict usa repr do Python — a saída exibe True/None (sintaxe Python), não true/null (sintaxe JSON). Não é JSON válido.
Solução: Use sempre json.dumps(data, indent=4) para uma saída JSON válida e legível.
data = {"ativo": True, "contador": None}
print(data)
# {'ativo': True, 'contador': None}print(json.dumps(data, indent=4))
# {
# "ativo": true,
# "contador": null
# }Problema: Caracteres especiais (letras acentuadas, emojis) são escapados para sequências \\uXXXX, tornando a saída ilegível.
Solução: Passe ensure_ascii=False para preservar os caracteres Unicode originais.
usuario = {"nome": "Camila Rocha", "cidade": "São Paulo"}
json.dumps(usuario, indent=2)
# {"nome": "Camila Rocha", "cidade": "S\u00e3o Paulo"}json.dumps(usuario, indent=2, ensure_ascii=False)
# {"nome": "Camila Rocha", "cidade": "São Paulo"}Problema: json.dumps() retorna uma string; você precisa de uma chamada f.write() separada, criando uma string intermediária desnecessária.
Solução: Use json.dump(data, f, indent=4) — escreve diretamente no objeto arquivo.
with open("saida.json", "w") as f:
f.write(json.dumps(data, indent=4))with open("saida.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)Problema: pprint.pprint() usa sintaxe Python (True, None, aspas simples) que os parsers JSON rejeitam.
Solução: Use json.dumps(indent=4) para qualquer saída que precise ser parseável como JSON.
import pprint
pprint.pprint({"executando": True, "ultimo_erro": None})
# {'executando': True, 'ultimo_erro': None}import json
print(json.dumps({"executando": True, "ultimo_erro": None}, indent=4))
# {"executando": true, "ultimo_erro": null}Comparação de métodos — json.dumps, orjson, simplejson, rich
Use json.dumps() para formatação cotidiana e gravação de arquivos — cobre 95% dos casos sem dependências. Recorra a orjson quando serializar em um hot path ou quando seus objetos incluírem datetime e UUID. Use simplejson quando precisar de compatibilidade direta com a stdlib e suporte a Decimal pronto para usar. Reserve rich.print_json() e pprint estritamente para inspeção local no terminal — nenhum dos dois produz saída legível por máquinas.
Perguntas Frequentes
Como faço para formatar JSON de forma legível em Python?
Chame json.dumps(data, indent=4). O parâmetro indent define os espaços por nível de aninhamento. Importe o módulo json primeiro — ele vem incluído na biblioteca padrão do Python, sem necessidade de pip install. Passe ensure_ascii=False se seus dados contiverem caracteres acentuados, CJK ou outros não-ASCII.
import json
usuario = {"username": "jsilva", "plano": "enterprise", "permissoes": ["leitura", "escrita", "deploy"]}
print(json.dumps(usuario, indent=4, ensure_ascii=False))Qual é a diferença entre json.dumps() e json.dump()?
json.dumps() (com "s") retorna uma string formatada em memória. json.dump() (sem "s") escreve diretamente em um objeto arquivo — passe o handle do arquivo aberto como segundo argumento. Para gravar JSON formatado em disco, json.dump(data, f, indent=4) é o padrão idiomático e evita criar uma string intermediária.
# dumps → string em memória
formatado = json.dumps(data, indent=4)
# dump → escreve diretamente no arquivo
with open('saida.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)Por que json.dumps() exibe \u00e3\u00e9\u00f5 em vez do caractere real?
Por padrão ensure_ascii=True escapa todo caractere não-ASCII para sequências \uXXXX. Passe ensure_ascii=False para preservar os caracteres Unicode originais. Isso é especialmente importante para nomes, endereços e qualquer conteúdo gerado por usuários em português ou outros idiomas não-latinos.
data = {"cidade": "São Paulo", "saudacao": "Olá!", "pais": "Brasil"}
# Padrão — escapado
json.dumps(data, indent=4)
# {"cidade": "S\u00e3o Paulo", "saudacao": "Ol\u00e1!", ...}
# Legível
json.dumps(data, indent=4, ensure_ascii=False)
# {"cidade": "São Paulo", "saudacao": "Olá!", "pais": "Brasil"}Como formato uma string JSON (não um dict)?
Primeiro faça o parse da string com json.loads(), depois formate com json.dumps(). As duas chamadas podem ser encadeadas em uma linha para inspeção rápida no terminal.
import json
raw = '{"endpoint":"/api/v2/pedidos","timeout":30,"tentar_novamente":true}'
print(json.dumps(json.loads(raw), indent=4))Posso usar pprint para formatar JSON em Python?
pprint.pprint() produz representação de objetos Python, não JSON válido. Usa True/False/None (sintaxe Python) em vez de true/false/null (sintaxe JSON). Nunca passe a saída do pprint para uma API ou parser JSON — use json.dumps(indent=4) para qualquer saída que precise ser JSON válido.
import pprint, json
data = {"ativo": True, "pontuacao": None}
pprint.pprint(data) # {'ativo': True, 'pontuacao': None} ← não é JSON
json.dumps(data, indent=4) # {"ativo": true, "pontuacao": null} ← JSON válidoComo ordeno as chaves JSON alfabeticamente em Python?
Adicione sort_keys=True ao json.dumps(). Na linha de comando, use python -m json.tool --sort-keys data.json. Chaves ordenadas tornam os diffs de JSON legíveis e facilitam detectar o que mudou entre versões.
import json
servidor = {"workers": 4, "host": "0.0.0.0", "porta": 8080, "debug": False}
print(json.dumps(servidor, indent=4, sort_keys=True, ensure_ascii=False))
# {
# "debug": false,
# "host": "0.0.0.0",
# "porta": 8080,
# "workers": 4
# }O Python dá-lhe controlo total — serializadores personalizados, streaming, integração com pipeline. Quando só precisa de inspecionar ou partilhar um fragmento formatado, o Formatador JSON do ToolDeck é o caminho mais rápido: cole o seu JSON e obtenha um resultado indentado e destacado sem qualquer configuração de ambiente.
Ferramentas Relacionadas
Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.
Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.