Convertir JSON a Python
JSON a Python genera dataclasses, TypedDicts o modelos de Pydantic a partir de un documento de ejemplo, en tu navegador. Las tres cosas responden a preguntas distintas: una dataclass describe los datos sin dependencias, un TypedDict describe el dict que json.loads ya te dio, y un modelo de Pydantic lo valida en la frontera.
El documento termina antes de tiempo; parece incompleto.
^
¿Cómo funciona Convertir JSON a Python?
Elige la forma según lo que vayas a hacer con el resultado. Las tres no son intercambiables, y elegir la equivocada es el problema más común del Python generado.
dataclass, TypedDict, Pydantic
Una @dataclass te da un objeto de verdad con acceso por atributos, igualdad y un repr útil, y sin dependencias de terceros — pero no valida nada, así que un campo anotado como int guardará encantado el string con el que lo construiste. Un TypedDict anota el diccionario plano que json.loads ya devolvió, así que no hay que construir nada y aun así el verificador de tipos caza una clave mal escrita; es la respuesta correcta cuando pasas el JSON ya interpretado tal cual. Un BaseModel de Pydantic valida y convierte de verdad en la construcción, que es lo que un cliente de API quiere en su frontera, al precio de una dependencia y algo de trabajo en tiempo de ejecución.
El orden de los campos es un problema de corrección, no de estilo
Un campo de dataclass con valor por defecto no puede preceder a uno sin él: Python lanza TypeError al importar el módulo, no en el primer uso. Como los campos opcionales reciben = None, el generador emite primero todos los campos obligatorios. Un generador que aquí preserve el orden de las claves JSON produce un módulo que no se puede importar.
Optional significa «puede ser None», no «puede omitirse»
Esto despista a la gente en Python en particular, porque Optional[int] parece decir opcional y significa que admite null. En una dataclass, un campo que falta en algunos registros se emite como Optional[int] = None — la anotación lleva la nulidad y el valor por defecto lleva la ausencia. En un TypedDict las dos cosas están genuinamente separadas, así que una clave ausente es NotRequired[int] y un valor null es Optional[int].
Las claves renombradas conservan un alias
La convención de Python es snake_case, y el JSON de un servicio en JavaScript normalmente no lo es. Las claves se renombran y la original queda registrada — como comentario en una dataclass o un TypedDict, y como un Field(alias=…) real en Pydantic, donde cambia el comportamiento en lugar de solo documentarlo.
Las referencias adelantadas van entre comillas
Las clases anidadas se emiten antes que las clases que las usan, pero la anotación se escribe igualmente como una cadena, lo que mantiene el módulo importable si lo reordenas a mano.
Ejemplo
[
{ "userId": 1, "team": "ops" },
{ "userId": 2 }
]Generado
from dataclasses import dataclass
from typing import Optional
@dataclass
class User:
user_id: int # JSON key: userId
team: Optional[str] = None¿Qué opciones y casos límite admite Convertir JSON a Python?
| Parámetro | Tipo | Valor predeterminado | Comportamiento y casos límite |
|---|---|---|---|
| Forma | dataclass / TypedDict / pydantic | dataclass | dataclass para un objeto sin dependencias; TypedDict para anotar el dict que devuelve json.loads; pydantic cuando quieres que los valores se validen en el límite. |
| snake_case | booleano | on | Renombra las claves según la convención de Python. En pydantic esto se convierte en un alias real, por lo que el análisis coincide con el formato de la red; en otros casos se registra en un comentario y debes mapear las claves tú mismo. |
| X | None | booleano | off | Sintaxis de unión de Python 3.10+ en lugar de Optional[X]. Es más corta y elimina la importación de typing — pero es un error de sintaxis en 3.9 y versiones anteriores. |
| string | tipo de Python | str | Los formatos detectados no se mapean a datetime o UUID: json.loads devuelve cadenas, y anotar una como datetime sería una mentira a menos que algo la analice. |
| entero / número | tipo de Python | int / float | Separados según si alguna muestra tenía parte fraccional. Los enteros de Python tienen precisión arbitraria, por lo que no hay una distinción int64 que hacer aquí. |
| Campo opcional | anotación | Optional[T] = None | En un TypedDict, una clave ausente es NotRequired[T], que es la distinción que hace Python y que las otras dos formas no pueden. |
| Orden de los campos | obligatorios primero | garantizado | Un campo de dataclass sin un valor predeterminado no puede seguir a uno con valor predeterminado. Los campos obligatorios se emiten primero sin importar el orden de las claves JSON. |
| Objeto anidado | class | referencia entre comillas | Se promueve a su propia clase, definida antes de su uso, y referenciada por una referencia hacia adelante entre comillas para que el módulo sobreviva al reordenamiento. |
Preguntas frecuentes
¿Cuál elijo: dataclass, TypedDict o Pydantic?
Si los datos cruzan una frontera de confianza — una respuesta HTTP, un webhook, un archivo que alguien subió — usa Pydantic, porque es el único de los tres que realmente comprueba algo. Si estás anotando dicts que ya interpretaste y los pasas internamente, usa TypedDict, que no cuesta nada en tiempo de ejecución. Usa una dataclass cuando quieras un objeto de verdad y cero dependencias, aceptando que las anotaciones son documentación para tu verificador de tipos, no una garantía.
¿Por qué mis campos están en un orden distinto al de mi JSON?
Porque un campo de dataclass con valor por defecto no puede ir después de uno sin él — Python lanza TypeError cuando se importa el módulo, antes de que se ejecute cualquier parte de tu código. Los campos opcionales reciben = None, así que todos se mueven detrás de los obligatorios. TypedDict y Pydantic no tienen esa regla y conservan el orden original.
¿Optional[int] significa que la clave puede faltar?
No, y es la lectura errónea más común del tipado de Python. Optional[int] significa que el valor puede ser None. Que la clave pueda estar ausente es otra cuestión, expresada con un valor por defecto en una dataclass o con NotRequired en un TypedDict. El generador las distingue: una clave que falta en algunos registros recibe un valor por defecto, y un valor que es null en algunos registros recibe Optional.
¿Por qué mi marca de tiempo es str en lugar de datetime?
json.loads devuelve una cadena, así que anotarla como datetime sería mentir a menos que algo la interprete. En Pydantic puedes cambiar la anotación a datetime y te interpretará ISO 8601, una de las mejores razones para elegir Pydantic. En una dataclass o un TypedDict, cambiar la anotación no cambia nada en tiempo de ejecución y despista a cualquier lector.
¿Puedo usar el TypedDict generado en Python 3.9?
Sí — la importación es desde typing_extensions en lugar de typing, por eso está escrito así. NotRequired no llegó a la biblioteca estándar hasta la 3.11, y typing_extensions lo trae retroactivamente a todas las versiones que tienen TypedDict. Activar la opción X | None, en cambio, sí requiere 3.10.
¿Se sube mi JSON?
No. El análisis, la inferencia y el renderizado ocurren todos en tu navegador, algo que puedes verificar en el panel Network. Generar una clase a partir de un ejemplo no requiere para nada un servidor, y los ejemplos que la gente pega suelen ser payloads reales de un sistema con el que se están integrando.