Python JSON
Aprenda a usar o módulo json do Python para codificar, decodificar, ler e escrever dados JSON, com exemplos práticos e tratamento de erros.
O módulo json embutido do Python permite converter entre objetos Python e texto JSON com apenas duas funções na maioria dos casos. Este capítulo cobre tudo o que você precisa: mapeamento de tipos de dados, dumps/loads para strings, dump/load para arquivos, impressão formatada, tratamento de erros e serialização personalizada.
O que é JSON?
JSON (JavaScript Object Notation) é um formato leve de intercâmbio de dados baseado em texto. É legível por humanos, independente de linguagem e o formato padrão para a maioria das APIs web.
Um documento JSON é construído a partir de duas estruturas:
- Objects — coleções não ordenadas de pares chave/valor delimitadas por
{}. As chaves são sempre strings entre aspas duplas. - Arrays — sequências ordenadas de valores delimitadas por
[].
Exemplo de documento JSON:
{
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "traveling", "photography"],
"active": true,
"score": null
}Mapeamento de tipos Python–JSON
Ao codificar ou decodificar JSON, o módulo json do Python converte os tipos de acordo com esta tabela:
| Tipo Python | Tipo JSON | Tipo Python (após decodificação) |
|---|---|---|
dict | object {} | dict |
list, tuple | array [] | list |
str | string "" | str |
int, float | number | int ou float |
True / False | true / false | bool |
None | null | None |
Observe que tuplas se tornam arrays JSON e retornam como listas Python após a decodificação.
Codificando objetos Python em strings JSON
json.dumps() (dump-string) serializa um objeto Python em uma string formatada como JSON.
Codificação básica
Saída:
{"name": "John Doe", "age": 30, "city": "New York", "hobbies": ["reading", "traveling", "photography"]}Impressão formatada com indent e sort_keys
Por padrão, json.dumps() produz uma string compacta em uma única linha. Passe indent para produzir saída legível por humanos, e sort_keys=True para ordenar as chaves do dicionário em ordem alfabética:
import json
person = {
"name": "John Doe",
"age": 30,
"city": "New York",
"hobbies": ["reading", "traveling", "photography"]
}
print(json.dumps(person, indent=2, sort_keys=True))Saída:
{
"age": 30,
"city": "New York",
"hobbies": [
"reading",
"traveling",
"photography"
],
"name": "John Doe"
}Use indent=2 ou indent=4 ao escrever arquivos de configuração ou depurar respostas de API — isso facilita a leitura de estruturas aninhadas.
Decodificando strings JSON em objetos Python
json.loads() (load-string) analisa uma string JSON e retorna o objeto Python equivalente.
Decodificação básica
Saída:
{'name': 'John Doe', 'age': 30, 'city': 'New York', 'hobbies': ['reading', 'traveling', 'photography']}
<class 'dict'>
John DoeO valor decodificado é um dicionário Python comum, portanto você pode acessar suas chaves com [] ou .get(), iterá-lo com for, e assim por diante.
Tratando JSON malformado
Se a entrada não for um JSON válido, json.loads() lança json.JSONDecodeError. Sempre capture-o ao trabalhar com dados de fontes externas:
import json
raw = '{"name": "Alice", "age":}' # invalid — missing value
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
print(f"Invalid JSON: {e}")Saída:
Invalid JSON: Expecting value: line 1 column 24 (char 23)Consulte o capítulo Python try/except para um guia completo sobre tratamento de exceções.
Trabalhando com JSON aninhado
Objetos JSON podem conter outros objetos e arrays em qualquer profundidade. Acesse valores aninhados usando notação [] encadeada:
Saída:
John
travelingPara estruturas profundamente aninhadas, considere usar .get() com um valor padrão para evitar KeyError em chaves ausentes:
city = person.get("address", {}).get("city", "unknown")O capítulo de dicionários aninhados cobre padrões para trabalhar com dicionários Python profundamente aninhados.
Lendo e escrevendo arquivos JSON
json.dump() escreve em um objeto de arquivo, e json.load() lê de um. Estes são os equivalentes de arquivo de dumps/loads.
Escrevendo JSON em um arquivo
import json
data = {"name": "Alice", "scores": [95, 87, 92]}
with open("data.json", "w") as f:
json.dump(data, f, indent=2)Isso cria data.json com conteúdo formatado. Usar with open(...) garante que o arquivo seja fechado automaticamente — veja tratamento de arquivos em Python para mais detalhes.
Lendo JSON de um arquivo
import json
with open("data.json") as f:
data = json.load(f)
print(data)
print(data["scores"])Saída (considerando o arquivo escrito acima):
{'name': 'Alice', 'scores': [95, 87, 92]}
[95, 87, 92]Exemplo completo de ida e volta
import json
# Write
config = {"host": "localhost", "port": 5432, "debug": False}
with open("config.json", "w") as f:
json.dump(config, f, indent=2)
# Read back
with open("config.json") as f:
loaded = json.load(f)
print(loaded["port"]) # 5432
print(type(loaded["port"])) # <class 'int'>Obtendo JSON de uma API web
Na maioria dos projetos, você vai decodificar JSON proveniente de uma resposta HTTP. A popular biblioteca requests torna isso simples:
import requests
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
response.raise_for_status() # raises an error for 4xx/5xx responses
data = response.json() # equivalent to json.loads(response.text)
print(data["title"])
print(data["completed"])response.json() chama json.loads() internamente. Sempre chame raise_for_status() antes de analisar para que uma requisição com falha não retorne silenciosamente um corpo de erro.
Serialização personalizada com default
O módulo json não consegue codificar objetos Python arbitrários (como datetime.date) por padrão. Passe um callable default ou uma subclasse personalizada de JSONEncoder para tratá-los:
import json
import datetime
class DateEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.date):
return obj.isoformat()
return super().default(obj)
event = {"name": "Conference", "date": datetime.date(2024, 1, 15)}
print(json.dumps(event, cls=DateEncoder))Saída:
{"name": "Conference", "date": "2024-01-15"}O objeto date é convertido para sua string ISO 8601 antes da serialização.
Desserialização personalizada com object_hook
object_hook é chamado para cada object JSON (dict) à medida que é decodificado. Você pode usá-lo para transformar dados durante a execução — por exemplo, convertendo valores string para os tipos Python corretos:
import json
def as_record(d):
"""Convert age field from string to int if present."""
if "age" in d:
d["age"] = int(d["age"])
return d
raw = '{"name": "Bob", "age": "25"}'
person = json.loads(raw, object_hook=as_record)
print(person)
print(type(person["age"])) # <class 'int'>Saída:
{'name': 'Bob', 'age': 25}
<class 'int'>Referência rápida
| Função | Direção | Fonte/destino |
|---|---|---|
json.dumps(obj) | Python → JSON | retorna uma str |
json.loads(s) | JSON → Python | lê de uma str |
json.dump(obj, f) | Python → JSON | escreve em um arquivo |
json.load(f) | JSON → Python | lê de um arquivo |
Parâmetros opcionais principais:
indent=2— impressão formatada com recuo de 2 espaçossort_keys=True— ordena as chaves do dicionário em ordem alfabéticacls=MyEncoder— usa uma subclasse personalizada deJSONEncoderobject_hook=fn— transforma cada object dict decodificado