Converter JSON em Python
O JSON para Python gera dataclasses, TypedDicts ou modelos Pydantic a partir de um documento de exemplo no seu navegador. Os três respondem a perguntas diferentes: uma dataclass descreve os dados sem nenhuma dependência, um TypedDict descreve o dict que o json.loads já te deu, e um modelo Pydantic valida isso na fronteira.
O documento termina cedo demais — parece incompleto.
^
Como funciona o Converter JSON em Python?
Escolha o formato pensando no que você pretende fazer com o resultado. Os três não são intercambiáveis, e escolher o errado é o problema mais comum com Python gerado.
dataclass, TypedDict, Pydantic
Uma @dataclass te dá um objeto de verdade, com acesso por atributo, igualdade e um repr útil, e nenhuma dependência de terceiros — mas não faz validação nenhuma, então um campo anotado como int aceita de bom grado um string passado na sua construção. Um TypedDict anota o dicionário simples que o json.loads já retornou, então nada precisa ser construído e o type checker ainda pega uma chave com erro de digitação; é a resposta certa quando você está passando JSON parseado adiante como está. Um BaseModel do Pydantic de fato valida e converte na construção, que é o que um cliente de API quer na sua fronteira, ao custo de uma dependência e de algum trabalho em tempo de execução.
A ordem dos campos é um problema de correção, não de estilo
Um campo de dataclass com valor padrão não pode vir antes de um sem: Python levanta TypeError na hora do import, não no primeiro uso. Como os campos opcionais recebem = None, o gerador emite todos os campos obrigatórios primeiro. Um gerador que preserva a ordem das chaves de JSON aqui produz um módulo que falha ao importar.
Optional significa "pode ser None", não "pode ser omitido"
Isso confunde as pessoas especificamente em Python, porque Optional[int] parece significar opcional, mas significa anulável. Em uma dataclass, um campo ausente em alguns registros é emitido como Optional[int] = None — a anotação carrega a anulabilidade e o padrão carrega a ausência. Em um TypedDict as duas coisas são de fato separadas, então uma chave ausente é NotRequired[int] e um valor null é Optional[int].
Chaves renomeadas mantêm um alias
A convenção de Python é snake_case, e o JSON de um serviço JavaScript geralmente não é. As chaves são renomeadas e a original fica registrada — como comentário em uma dataclass ou TypedDict, e como um Field(alias=…) de verdade no Pydantic, onde isso muda o comportamento em vez de apenas documentá-lo.
Referências futuras vão entre aspas
As classes aninhadas são emitidas antes das classes que as usam, mas a anotação ainda é escrita como string, o que mantém o módulo importável se você reordená-lo à mão.
Exemplo
[
{ "userId": 1, "team": "ops" },
{ "userId": 2 }
]Gerado
from dataclasses import dataclass
from typing import Optional
@dataclass
class User:
user_id: int # JSON key: userId
team: Optional[str] = NoneQuais opções e casos-limite o Converter JSON em Python suporta?
| Parâmetro | Tipo | Padrão | Comportamento e casos-limite |
|---|---|---|---|
| Formato | dataclass / TypedDict / pydantic | dataclass | dataclass para um objeto sem dependências; TypedDict para anotar o dict retornado por json.loads; pydantic quando você quer que os valores sejam validados na fronteira. |
| snake_case | booleano | on | Renomeia as chaves para a convenção Python. Em pydantic isso se torna um alias real, então o parsing ainda corresponde ao formato de rede; em outros lugares é registrado em um comentário e você deve mapear as chaves você mesmo. |
| X | None | booleano | off | Sintaxe de união do Python 3.10+ em vez de Optional[X]. Mais curta, e elimina a importação de typing — mas é um erro de sintaxe no 3.9 e abaixo. |
| string | tipo Python | str | Formatos detectados não são mapeados para datetime ou UUID: json.loads retorna strings, e anotar uma como datetime seria uma mentira a menos que algo a tenha analisado. |
| inteiro / número | tipo Python | int / float | Separado por se algum exemplo tinha parte fracionária. Inteiros Python são de precisão arbitrária, então não há distinção int64 a ser feita aqui. |
| Campo opcional | anotação | Optional[T] = None | Em um TypedDict uma chave ausente é NotRequired[T] em vez disso, que é a distinção que o Python faz e as outras duas formas não podem. |
| Ordem dos campos | obrigatórios primeiro | garantida | Um campo dataclass sem um valor padrão não pode vir após um com valor padrão. Campos obrigatórios são emitidos primeiro, independentemente da ordem das chaves JSON. |
| Objeto aninhado | classe | referência entre aspas | Promovido para sua própria classe, definida antes do uso, e referenciada por uma referência forward entre aspas para que o módulo sobreviva à reordenação. |
Perguntas frequentes
Qual devo escolher: dataclass, TypedDict ou Pydantic?
Se os dados cruzam uma fronteira de confiança — uma resposta HTTP, um webhook, um arquivo que alguém enviou — use Pydantic, porque é o único dos três que de fato verifica alguma coisa. Se você está anotando dicts que já parseou e passando-os internamente, use TypedDict, que não custa nada em tempo de execução. Use uma dataclass quando quiser um objeto de verdade e nenhuma dependência, aceitando que as anotações são documentação para o seu type checker, e não uma garantia.
Por que meus campos estão em uma ordem diferente do meu JSON?
Porque um campo de dataclass com valor padrão não pode vir depois de um sem — Python levanta TypeError quando o módulo é importado, antes de qualquer código seu rodar. Campos opcionais recebem = None, então todos são movidos para depois dos obrigatórios. TypedDict e Pydantic não têm essa regra e mantêm a ordem original.
Optional[int] significa que a chave pode estar ausente?
Não, e essa é a leitura errada mais comum na tipagem de Python. Optional[int] significa que o valor pode ser None. Se a chave pode estar ausente é uma pergunta separada, expressa por um valor padrão em uma dataclass ou por NotRequired em um TypedDict. O gerador distingue os dois: uma chave ausente em alguns registros ganha um padrão, um valor que é null em alguns registros ganha Optional.
Por que meu timestamp é str em vez de datetime?
O json.loads retorna um string, então anotá-lo como datetime seria falso, a menos que algo o parseie. No Pydantic você pode mudar a anotação para datetime e ele parseia ISO 8601 para você, o que é um dos melhores motivos para escolher Pydantic. Em uma dataclass ou TypedDict, mudar a anotação não muda nada em tempo de execução e engana todo leitor.
Posso usar o TypedDict gerado no Python 3.9?
Sim — o import é de typing_extensions em vez de typing, e é por isso que ele é escrito assim. O NotRequired só chegou à biblioteca padrão no 3.11, e o typing_extensions o porta de volta para toda versão que tenha TypedDict, pelo menos. Já ligar a opção X | None, por outro lado, exige o 3.10.
Meu JSON é enviado?
Não. Parse, inferência e renderização acontecem todos no seu navegador, o que você pode conferir no painel Network. Nada em gerar uma classe a partir de um exemplo exige um servidor, e os exemplos que as pessoas colam costumam ser payloads reais de um sistema com o qual estão fazendo integração.