---
title: "JSON: O que É e Como Funciona | Python Brasil"
url: "https://python.dev.br/glossario/json/"
markdown_url: "https://python.dev.br/glossario/json.MD"
description: "Aprenda a trabalhar com JSON em Python: serializar, deserializar, ler e gravar arquivos, APIs e boas praticas para manipulacao de dados estruturados."
date: "2025-07-20"
author: ""
---

# 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:

```python
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)

```python
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)

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

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

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

```python
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)

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

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

> **JSON em outras linguagens**: <a href="https://golang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'golang.com.br', content: 'glossario-json'})">Go usa struct tags para serialização JSON</a> de forma nativa e tipada, enquanto <a href="https://rustlang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'rustlang.com.br', content: 'glossario-json'})">Rust com serde é referência em serialização de alta performance</a>.
