JSON: O que É e Como Funciona | Python Brasil
Aprenda a trabalhar com JSON em Python: serializar, deserializar, ler e gravar arquivos, APIs e boas praticas para manipulacao de dados estruturados.
O que e JSON?
JSON (JavaScript Object Notation) e um formato leve de troca de dados, facil de ler e escrever para humanos e simples de interpretar e gerar para maquinas. Apesar do nome fazer referencia a JavaScript, JSON e independente de linguagem e se tornou o formato padrao para comunicacao entre APIs, arquivos de configuracao e armazenamento de dados estruturados.
Python possui o modulo embutido json que oferece suporte completo para codificar (serializar) objetos Python em strings JSON e decodificar (deserializar) strings JSON em objetos Python.
Correspondencia de Tipos
A tabela de conversao entre tipos JSON e Python e direta:
import json
# JSON -> Python
# object -> dict
# array -> list
# string -> str
# number (int) -> int
# number (float) -> float
# true -> True
# false -> False
# null -> None
Serializacao (Python para JSON)
import json
# Dicionario para string JSON
dados = {
'nome': 'Ana Silva',
'idade': 28,
'ativo': True,
'habilidades': ['Python', 'SQL', 'Docker'],
'endereco': {
'cidade': 'Sao Paulo',
'estado': 'SP',
},
'telefone': None,
}
# Converter para string JSON
json_str = json.dumps(dados)
print(json_str)
# Com formatacao legivel
json_formatado = json.dumps(dados, indent=2, ensure_ascii=False)
print(json_formatado)
# Gravar em arquivo
with open('dados.json', 'w', encoding='utf-8') as f:
json.dump(dados, f, indent=2, ensure_ascii=False)
Deserializacao (JSON para Python)
import json
# String JSON para dicionario
json_str = '{"nome": "Bruno", "idade": 25, "ativo": true}'
dados = json.loads(json_str)
print(dados['nome']) # 'Bruno'
print(type(dados)) # <class 'dict'>
# Ler de arquivo
with open('dados.json', 'r', encoding='utf-8') as f:
dados = json.load(f)
print(dados)
# Lista JSON
json_lista = '[1, 2, 3, "quatro", null]'
lista = json.loads(json_lista)
print(lista) # [1, 2, 3, 'quatro', None]
Serializacao de Tipos Customizados
O modulo json nao sabe serializar todos os tipos Python. Para tipos como datetime, Decimal e classes customizadas, e necessario criar um encoder personalizado.
import json
from datetime import datetime, date
from decimal import Decimal
# Usando default para tipos customizados
def serializador_customizado(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, Decimal):
return float(obj)
if isinstance(obj, set):
return list(obj)
raise TypeError(f'Tipo {type(obj)} nao e serializavel')
dados = {
'criado_em': datetime.now(),
'preco': Decimal('49.99'),
'tags': {'python', 'tutorial'},
}
json_str = json.dumps(dados, default=serializador_customizado, indent=2)
print(json_str)
# Usando JSONEncoder customizado
class MeuEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, Decimal):
return str(obj)
return super().default(obj)
json_str = json.dumps(dados, cls=MeuEncoder, indent=2)
Trabalhando com APIs
import json
from urllib.request import urlopen, Request
# GET request
url = 'https://jsonplaceholder.typicode.com/posts/1'
with urlopen(url) as response:
dados = json.loads(response.read().decode())
print(dados['title'])
# POST request com JSON
dados_envio = {'title': 'Novo Post', 'body': 'Conteudo', 'userId': 1}
req = Request(
'https://jsonplaceholder.typicode.com/posts',
data=json.dumps(dados_envio).encode('utf-8'),
headers={'Content-Type': 'application/json'},
method='POST',
)
with urlopen(req) as response:
resultado = json.loads(response.read().decode())
print(resultado)
Validacao e Tratamento de Erros
import json
# Tratar JSON invalido
texto_invalido = "{'chave': 'valor'}" # aspas simples nao sao JSON valido
try:
dados = json.loads(texto_invalido)
except json.JSONDecodeError as e:
print(f'Erro ao decodificar JSON: {e}')
print(f'Linha: {e.lineno}, Coluna: {e.colno}')
# Funcao segura para parsing
def parse_json_seguro(texto: str, padrao=None):
"""Tenta parsear JSON, retorna valor padrao se falhar."""
try:
return json.loads(texto)
except (json.JSONDecodeError, TypeError):
return padrao
resultado = parse_json_seguro('invalido', padrao={})
print(resultado) # {}
JSON Lines (JSONL)
import json
# JSONL: um objeto JSON por linha — util para logs e dados em streaming
registros = [
{'id': 1, 'nome': 'Ana', 'nota': 9.5},
{'id': 2, 'nome': 'Bruno', 'nota': 7.8},
{'id': 3, 'nome': 'Carla', 'nota': 8.3},
]
# Gravar JSONL
with open('dados.jsonl', 'w') as f:
for registro in registros:
f.write(json.dumps(registro, ensure_ascii=False) + '\n')
# Ler JSONL
with open('dados.jsonl', 'r') as f:
dados = [json.loads(linha) for linha in f if linha.strip()]
Opcoes Uteis de json.dumps
import json
dados = {'z_campo': 1, 'a_campo': 2, 'nome': 'Python'}
# sort_keys — ordena as chaves alfabeticamente
print(json.dumps(dados, sort_keys=True))
# separators — controla separadores para JSON compacto
compacto = json.dumps(dados, separators=(',', ':'))
print(compacto) # {"z_campo":1,"a_campo":2,"nome":"Python"}
# ensure_ascii=False — preserva caracteres nao-ASCII
dados_br = {'cidade': 'Sao Paulo', 'descricao': 'Capital paulista'}
print(json.dumps(dados_br, ensure_ascii=False))
Erros Comuns
O erro mais frequente e tentar serializar tipos que o modulo json nao suporta nativamente, como datetime, Decimal, set e classes customizadas, sem fornecer um serializador. Outro erro e usar aspas simples em strings JSON manuais — JSON exige aspas duplas. Tambem e comum esquecer de especificar encoding='utf-8' ao ler ou gravar arquivos JSON com caracteres acentuados, e nao tratar JSONDecodeError ao receber dados de fontes externas.
Boas Praticas
Sempre use ensure_ascii=False ao trabalhar com texto em portugues para manter a legibilidade. Use indent=2 para arquivos de configuracao e dados que humanos vao ler. Para dados de API ou armazenamento, omita o indent para economizar espaco. Trate sempre excecoes ao parsear JSON de fontes externas. Para projetos que exigem validacao de esquema, considere bibliotecas como Pydantic.
Quando Usar
JSON e o formato padrao para troca de dados em APIs REST, arquivos de configuracao, comunicacao entre microservicos e armazenamento de dados semi-estruturados. Em Python, o modulo json e suficiente para a maioria dos casos. Para necessidades de alta performance, considere orjson ou ujson.