JSON Formatter Python — Guia do json.dumps()

·Backend Developer·Revisado porDmitri Volkov·Publicado

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

Pontos Principais
  • json.dumps(data, indent=4) está integrado na stdlib do Python desde a versão 2.6 — sem instalação.
  • Passe ensure_ascii=False sempre que seus dados contiverem letras acentuadas, caracteres CJK ou emojis.
  • Para datetime, UUID ou classes personalizadas, use o parâmetro default= ou crie uma subclasse de json.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 gerencia datetime e uuid.UUID de 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 ijson em vez de json.load() para evitar MemoryError.

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.

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

Python 3.8+ — exemplo mínimo
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):

Python 3.8+ — com sort_keys e ensure_ascii
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"
# }
Nota: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.

Parâmetro
Tipo
Default
Descrição
obj
any
Objeto Python a serializar em uma string com formato JSON.
indent
int | str | None
None
Espaços por nível de indentação. None = linha única compacta, 0 = apenas quebras de linha, 4 = padrão.
sort_keys
bool
False
Ordena as chaves do dicionário alfabeticamente em todos os níveis aninhados.
ensure_ascii
bool
True
Escapa caracteres não-ASCII para \uXXXX. Passe False para preservar os caracteres Unicode originais.
separators
tuple | None
None
Par (sep_item, sep_chave). Use (",", ":") para a saída mais compacta possível.
default
callable | None
None
Chamado para tipos não serializáveis. Lance TypeError para rejeitar o valor.
allow_nan
bool
True
Serializa float("nan") e float("inf") como literais JS. Passe False para lançar ValueError.

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.

Python 3.8+
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"}
Nota:Ao passar 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.

Python 3.8+ — TypeError sem tratamento personalizado
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 TypeError

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

Python 3.8+
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.

Python 3.8+
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=
Nota:Sempre chame 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.

Python 3.8+
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:00
Nota:O object_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.

Python 3.8+
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
# }
Aviso:Nunca envie a saída do 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

Python 3.8+
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

Python 3.8+ (requer: pip install requests)
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")
Nota: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.

bash
# 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
Nota:O Python 3.9 adicionou as opções --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.

bash — instalar
pip install orjson
Python 3.8+
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.

bash — instalar
pip install rich
Python 3.8+
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))
Aviso: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.

bash — instalar
pip install simplejson
Python 3.8+
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
# }
Nota:Para desempenho puro, 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.

bash — instalar
pip install ijson
Python 3.8+
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ória
Nota:Migre de json.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.

Python 3.8+
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.

Usar print(data) em vez de json.dumps()

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.

Before · Python
After · Python
data = {"ativo": True, "contador": None}
print(data)
# {'ativo': True, 'contador': None}
print(json.dumps(data, indent=4))
# {
#     "ativo": true,
#     "contador": null
# }
Esquecer ensure_ascii=False com texto em português

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.

Before · Python
After · Python
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"}
Usar json.dumps() para gravar em um arquivo

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.

Before · Python
After · Python
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)
Usar pprint esperando JSON válido

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.

Before · Python
After · Python
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.

Método
Saída
JSON válido
Velocidade
Não-ASCII
Tipos custom
Instalação
json.dumps(indent=4)
String
Padrão
ensure_ascii=False
default= / JSONEncoder
Integrado
json.dump(f, indent=4)
Arquivo
Padrão
ensure_ascii=False
default= / JSONEncoder
Integrado
pprint.pprint()
repr Python
Padrão
Nativo
✅ (qualquer repr)
Integrado
orjson.dumps(OPT_INDENT_2)
Bytes
5–10× mais rápido
Nativo
datetime, UUID, numpy
pip install orjson
python -m json.tool
stdout CLI
Padrão
Integrado
simplejson.dumps()
String
~1.5× mais rápido
ensure_ascii=False
Decimal nativo
pip install simplejson
rich.print_json()
Só terminal
✅ (entrada)
Padrão
pip install rich

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.

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

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

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

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

python
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álido

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

python
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

Também disponível em:GoJavaScriptBash
MS
Maria SantosBackend Developer

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.

DV
Dmitri VolkovRevisor técnico

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.