JSON (JavaScript Object Notation) é o formato de troca de dados mais utilizado na web moderna. Praticamente toda API REST retorna JSON, arquivos de configuração usam JSON, e bancos de dados NoSQL como MongoDB armazenam dados nesse formato. O Python oferece suporte nativo e extremamente poderoso para JSON através do módulo json, parte da biblioteca padrão.

Neste guia completo, você vai aprender tudo sobre manipulação de dados JSON com Python: desde a serialização básica com json.dumps() e json.loads() até técnicas avançadas como codificadores personalizados, validação com JSON Schema e integração com APIs REST. Vamos começar!

O Que é JSON?

JSON é um formato de texto leve para armazenar e transportar dados estruturados. Ele foi especificado originalmente por Douglas Crockford no JSON.org e posteriormente padronizado pela RFC 7159. Sua sintaxe é simples e legível tanto para humanos quanto para máquinas.

JSON suporta apenas seis tipos de dados:

  • String: sequência de caracteres entre aspas duplas
  • Number: inteiros ou decimais (ponto flutuante)
  • Boolean: true ou false
  • Null: valor nulo (null)
  • Array: lista ordenada de valores entre colchetes []
  • Object: coleção de pares chave/valor entre chaves {}
{
  "nome": "Python",
  "versao": 3.12,
  "paradigmas": ["Orientado a Objetos", "Funcional", "Imperativo"],
  "tipagem": "dinâmica",
  "open_source": true,
  "criador": null
}

Segundo a MDN Web Docs, JSON é um formato que se destaca por sua simplicidade e ubiquidade na web, sendo suportado nativamente por todas as linguagens de programação modernas.

O Módulo json do Python

O Python inclui o módulo json como parte de sua biblioteca padrão. Isso significa que você não precisa instalar nada, basta importá-lo e começar a usar. A documentação oficial do módulo json é o ponto de partida ideal para consultas aprofundadas.

import json

O módulo oferece quatro funções principais que formam a base de toda manipulação de JSON em Python:

  • json.dumps(): converte um objeto Python em uma string JSON
  • json.loads(): converte uma string JSON em um objeto Python
  • json.dump(): escreve um objeto Python diretamente em um arquivo JSON
  • json.load(): lê um arquivo JSON e o converte em objeto Python

json.dumps(): Serializando Python para JSON

A função json.dumps() (dump string) serializa um objeto Python em uma string JSON. A tabela de conversão segue o mapeamento padrão:

  • dictObject {}
  • list, tupleArray []
  • strString
  • int, floatNumber
  • Truetrue
  • Falsefalse
  • Nonenull
import json

dados = { "linguagem": "Python", "criado_em": 1991, "tipos": ["int", "float", "str", "list", "dict"], "interpretada": True, "autor": None }

json_string = json.dumps(dados) print(json_string)

Saída: {"linguagem": "Python", "criado_em": 1991, "tipos": ["int", "float", "str", "list", "dict"], "interpretada": true, "autor": null}

Observe como True se torna true e None se torna null automaticamente, seguindo o padrão JSON.

Parâmetros Avançados do dumps()

O json.dumps() oferece vários parâmetros para controlar a saída:

import json

dados = {"nome": "Python", "versao": 3.12, "features": ["simples", "poderoso"]}

indent, formata com indentação para legibilidade

print(json.dumps(dados, indent=2))

sort_keys, ordena as chaves alfabeticamente

print(json.dumps(dados, indent=2, sort_keys=True))

ensure_ascii, se False, permite caracteres Unicode

print(json.dumps({"nome": "João"}, ensure_ascii=False))

Saída: {"nome": "João"}

separators, personaliza separadores (remove espaços)

print(json.dumps(dados, separators=(",", ":")))

Saída: {"nome":"Python","versao":3.12,"features":["simples","poderoso"]}

O parâmetro ensure_ascii=False é essencial quando você trabalha com textos em português ou outros idiomas com acentos e caracteres especiais, como explica o tutorial da Real Python sobre JSON.

json.loads(): Convertendo JSON para Python

A função json.loads() (load string) faz o caminho inverso: recebe uma string JSON e a converte em um objeto Python.

import json

json_string = '{"nome": "Python", "versao": 3.12, "interpretada": true, "autor": null}'

dados = json.loads(json_string) print(dados)

Saída: {'nome': 'Python', 'versao': 3.12, 'interpretada': True, 'autor': None}

print(type(dados))

Saída: <class 'dict'>

Perceba que a conversão respeita o mapeamento inverso: true vira True, null vira None, e strings JSON viram strings Python. O resultado é sempre um dicionário Python quando o JSON de origem é um objeto.

json.dump() e json.load(): Trabalhando com Arquivos

As funções json.dump() e json.load() (sem o "s" final) trabalham diretamente com arquivos, evitando a necessidade de strings intermediárias. Este tópico se complementa com o guia de Manipulação de Arquivos TXT, CSV e JSON.

import json

Escrevendo JSON em um arquivo

dados = { "nome": "Python", "ano": 1991, "frameworks": ["Django", "Flask", "FastAPI"] }

with open("dados.json", "w", encoding="utf-8") as arquivo: json.dump(dados, arquivo, indent=2, ensure_ascii=False)

Lendo JSON de um arquivo

with open("dados.json", "r", encoding="utf-8") as arquivo: dados_carregados = json.load(arquivo)

print(dados_carregados["nome"]) # Saída: Python

Sempre use a codificação utf-8 ao trabalhar com arquivos JSON para garantir a compatibilidade com caracteres acentuados e especiais.

Serializando Objetos Python Personalizados

Por padrão, o módulo json não sabe como serializar objetos de classes personalizadas. Tente executar o código abaixo e você receberá um TypeError:

import json

class Pessoa: def init(self, nome, idade): self.nome = nome self.idade = idade

p = Pessoa("Ana", 30) print(json.dumps(p)) # TypeError: Object of type Pessoa is not JSON serializable

Existem duas abordagens principais para resolver isso.

Método 1: Usando um Custom JSONEncoder

Crie uma subclasse de json.JSONEncoder e sobrescreva o método default(). A documentação oficial do JSONEncoder fornece todos os detalhes desta abordagem.

import json
from datetime import datetime

class Pessoa: def init(self, nome, idade): self.nome = nome self.idade = idade

class CustomEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Pessoa): return {"nome": obj.nome, "idade": obj.idade, "_tipo": "Pessoa"} if isinstance(obj, datetime): return obj.isoformat() return super().default(obj)

p = Pessoa("Ana", 30) data = datetime.now() print(json.dumps({"pessoa": p, "data": data}, cls=CustomEncoder, indent=2))

Método 2: Usando Pydantic

O Pydantic é uma biblioteca que oferece validação de dados e serialização nativa para JSON. É amplamente utilizado com FastAPI e é a abordagem recomendada para projetos profissionais.

from pydantic import BaseModel

class Pessoa(BaseModel): nome: str idade: int

p = Pessoa(nome="Ana", idade=30) print(p.model_dump_json(indent=2))

Saída: {"nome": "Ana", "idade": 30}

O método model_dump_json() do Pydantic já retorna uma string JSON válida, resolvendo a serialização de forma elegante e segura.

Lidando com Erros e Exceções

Ao trabalhar com dados JSON, especialmente aqueles vindos de fontes externas, é fundamental tratar erros de parsing. O módulo json levanta exceções específicas que devem ser capturadas:

import json

def processar_json(texto): try: dados = json.loads(texto) return dados except json.JSONDecodeError as e: print(f"Erro ao decodificar JSON: {e}") print(f"Posição do erro: linha {e.lineno}, coluna {e.colno}") return None

JSON inválido

json_invalido = '{"nome": "Python", versao: 3.12}' resultado = processar_json(json_invalido)

Saída: Erro ao decodificar JSON: ...

JSON válido

json_valido = '{"nome": "Python"}' resultado = processar_json(json_valido) print(resultado)

Saída: {'nome': 'Python'}

Sempre valide o JSON recebido antes de processá-lo. A combinação de try/except com json.JSONDecodeError garante que sua aplicação não quebre ao receber dados malformados.

Validação com JSON Schema

Para garantir que um JSON siga uma estrutura específica, você pode usar o JSON Schema. Esta especificação define contratos formais para a estrutura de documentos JSON, algo essencial em APIs e integrações entre sistemas.

from jsonschema import validate, ValidationError

schema = { "type": "object", "properties": { "nome": {"type": "string", "minLength": 1}, "idade": {"type": "integer", "minimum": 0}, "email": {"type": "string", "format": "email"} }, "required": ["nome", "email"] }

dados_validos = {"nome": "Ana", "idade": 30, "email": "[email protected]"} validate(instance=dados_validos, schema=schema) # OK, não levanta exceção

dados_invalidos = {"nome": "", "email": "invalido"} try: validate(instance=dados_invalidos, schema=schema) except ValidationError as e: print(f"Erro de validação: {e.message}")

Embora a biblioteca jsonschema precise ser instalada separadamente (pip install jsonschema), ela é extremamente útil para validar payloads de API, arquivos de configuração e qualquer dado JSON que precise de uma estrutura previsível.

JSON e APIs REST

JSON é o formato padrão de entrada e saída da maioria das APIs REST modernas. Quando você faz uma requisição HTTP para uma API, a resposta quase sempre vem em JSON. Veja como consumir e enviar JSON usando a biblioteca requests:

import json
import requests

Consumindo uma API que retorna JSON

response = requests.get("https://api.github.com/users/python") dados = response.json() # Equivalente a json.loads(response.text) print(f"Repositórios: {dados['public_repos']}")

Enviando JSON para uma API

payload = {"titulo": "Novo Post", "conteudo": "JSON com Python"} headers = {"Content-Type": "application/json"} response = requests.post( "https://jsonplaceholder.typicode.com/posts", data=json.dumps(payload), headers=headers ) print(response.json())

Para dominar completamente o consumo de APIs, confira o guia completo sobre Python Requests para requisições HTTP.

O FastAPI, um dos frameworks web mais populares do Python, usa o Pydantic para validar e serializar JSON automaticamente. A documentação do FastAPI sobre JSON Encoder mostra como o framework lida com tipos personalizados de forma transparente.

Boas Práticas e Performance

Ao trabalhar com JSON em Python, siga estas recomendações:

  • Sempre use ensure_ascii=False quando houver caracteres acentuados ou Unicode no conteúdo
  • Defina indent apenas em arquivos de configuração: em produção, omita para reduzir o tamanho dos dados trafegados
  • Use separators=(",", ":") em APIs para minimizar o payload JSON
  • Prefira Pydantic ou dataclasses para serialização de objetos em projetos maiores
  • Valide dados com JSON Schema quando a estrutura precisar ser garantida
  • Trate exceções com json.JSONDecodeError ao processar dados de fontes externas

Para projetos que exigem performance máxima, considere alternativas como orjson (escrito em Rust) ou ujson. O módulo nativo json do Python, porém, é suficiente para a grande maioria dos casos de uso e tem a vantagem de não exigir dependências externas.

O tutorial da W3Schools sobre Python JSON oferece exemplos adicionais e exercícios práticos para reforçar o aprendizado.

Conclusão

JSON e Python formam uma combinação poderosa e onipresente no desenvolvimento de software moderno. O módulo json da biblioteca padrão oferece todas as ferramentas necessárias para serializar, desserializar, ler e escrever dados JSON com apenas algumas linhas de código.

Neste guia, você aprendeu:

  • Os fundamentos do formato JSON e seus tipos de dados
  • As quatro funções principais: dumps(), loads(), dump(), load()
  • Como serializar objetos Python personalizados com JSONEncoder e Pydantic
  • Como tratar erros de parsing e validar estruturas com JSON Schema
  • Como integrar JSON com APIs REST usando a biblioteca requests
  • Boas práticas para performance e segurança

Com esse conhecimento, você está preparado para manipular dados JSON em qualquer projeto Python, seja uma aplicação web, um script de automação, uma API REST ou uma pipeline de dados. Para se aprofundar ainda mais, explore a documentação oficial e pratique com dados reais de APIs públicas.