JSON vers Python
Générer des dataclasses Python depuis du JSON
Entrée JSON
Sortie Python
Qu'est-ce que la conversion JSON vers dataclass Python ?
La conversion JSON vers dataclass Python prend un objet JSON brut et produit un ensemble de définitions de dataclasses Python avec des annotations de types précises. Le module dataclasses de Python, introduit dans la PEP 557 (Python 3.7), génère automatiquement les méthodes __init__, __repr__ et __eq__ à partir des champs annotés de la classe. Lorsque vous travaillez avec des API JSON, des fichiers de configuration ou des files de messages, les dataclasses donnent à vos données une structure typée que les éditeurs et les vérificateurs de types comme mypy peuvent contrôler dès le développement.
La fonction json.loads() de Python retourne des dicts et des listes simples. Cela fonctionne, mais sans aucune information de type : une clé mal orthographiée retourne None au lieu de lever une erreur, et votre éditeur ne peut pas autocompléter les noms de champs. Les dataclasses résolvent ce problème en associant chaque clé JSON à un champ nommé et typé. Les objets JSON imbriqués deviennent des définitions de dataclasses séparées, les tableaux deviennent des annotations List[T], et les valeurs nulles deviennent Optional[T] avec une valeur par défaut None.
Écrire ces définitions à la main est un travail mécanique. Vous lisez le JSON, déduisez le type de chaque champ depuis sa valeur, convertissez les clés camelCase ou snake_case selon les conventions Python, et gérez les cas particuliers comme les champs nullables et les tableaux à types mixtes. Un convertisseur fait tout cela en quelques millisecondes. Vous collez du JSON, vous obtenez du code de dataclass correct, et vous passez à la suite.
Pourquoi utiliser un convertisseur JSON vers Python ?
Traduire manuellement des structures JSON en définitions de classes Python implique de deviner les types à partir d'exemples de données, de réordonner les champs pour que les champs obligatoires précèdent les champs optionnels, et de tout mettre à jour à chaque modification d'API. Un convertisseur supprime toutes ces frictions.
Cas d'usage du JSON vers Python
Correspondance des types JSON vers Python
Chaque valeur JSON correspond à une annotation de type Python spécifique. Le tableau ci-dessous montre comment le convertisseur traduit chaque type JSON, avec la syntaxe du module typing (Python 3.7+) et la syntaxe native disponible à partir de Python 3.10.
| Type JSON | Exemple | Python (typing) | Python 3.10+ |
|---|---|---|---|
| string | "hello" | str | str |
| number (integer) | 42 | int | int |
| number (float) | 3.14 | float | float |
| boolean | true | bool | bool |
| null | null | Optional[str] | str | None |
| object | {"k": "v"} | @dataclass class | nested model |
| array of strings | ["a", "b"] | List[str] | list[str] |
| array of objects | [{"id": 1}] | List[Item] | list[Item] |
| mixed array | [1, "a"] | List[Any] | list[Any] |
Référence du décorateur dataclass
Le décorateur @dataclass accepte plusieurs paramètres qui modifient le comportement de la classe générée. Cette référence couvre les options les plus utiles lorsqu'on travaille avec des données issues de JSON.
| Décorateur / Champ | Comportement | À utiliser quand |
|---|---|---|
| @dataclass | Generates __init__, __repr__, __eq__ from field annotations | Standard dataclasses |
| @dataclass(frozen=True) | Makes instances immutable (hashable, no attribute reassignment) | Config objects, dict keys |
| @dataclass(slots=True) | Uses __slots__ for lower memory and faster attribute access | Python 3.10+, large datasets |
| @dataclass(kw_only=True) | All fields require keyword arguments in __init__ | Python 3.10+, many fields |
| field(default_factory=list) | Sets a mutable default without sharing state between instances | List/dict/set defaults |
dataclass vs Pydantic vs TypedDict
Python propose trois façons courantes de définir des structures typées depuis du JSON. Chacune convient à un cas d'usage différent. Les dataclasses sont l'option de la bibliothèque standard, sans dépendance. Pydantic ajoute une validation à l'exécution. TypedDict annote des dicts classiques sans créer de nouvelle classe.
Exemples de code
Ces exemples montrent comment utiliser les dataclasses générées en Python, comment les produire programmatiquement depuis JavaScript, et comment utiliser des approches alternatives comme Pydantic et les outils en ligne de commande.
from dataclasses import dataclass
from typing import List, Optional
import json
@dataclass
class Address:
street: str
city: str
zip: str
@dataclass
class User:
id: int
name: str
email: str
active: bool
score: float
address: Address
tags: List[str]
metadata: Optional[str] = None
raw = '{"id":1,"name":"Alice","email":"alice@example.com","active":true,"score":98.5,"address":{"street":"123 Main St","city":"Springfield","zip":"12345"},"tags":["admin","user"],"metadata":null}'
data = json.loads(raw)
# Reconstruct nested objects manually
addr = Address(**data["address"])
user = User(**{**data, "address": addr})
print(user.name) # -> Alice
print(user.address) # -> Address(street='123 Main St', city='Springfield', zip='12345')// Minimal JSON-to-Python-dataclass generator in JS
function jsonToPython(obj, name = "Root") {
const classes = [];
function infer(val, fieldName) {
if (val === null) return "Optional[str]";
if (typeof val === "string") return "str";
if (typeof val === "number") return Number.isInteger(val) ? "int" : "float";
if (typeof val === "boolean") return "bool";
if (Array.isArray(val)) {
const first = val.find(v => v !== null);
return first ? `List[${infer(first, fieldName + "Item")}]` : "List[Any]";
}
if (typeof val === "object") {
const clsName = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
build(val, clsName);
return clsName;
}
return "Any";
}
function build(obj, cls) {
const fields = Object.entries(obj).map(([k, v]) => ` ${k}: ${infer(v, k)}`);
classes.push(`@dataclass\nclass ${cls}:\n${fields.join("\n")}`);
}
build(obj, name);
return classes.join("\n\n");
}
const data = { id: 1, name: "Alice", scores: [98, 85] };
console.log(jsonToPython(data, "User"));
// @dataclass
// class User:
// id: int
// name: str
// scores: List[int]from pydantic import BaseModel
from typing import List, Optional
class Address(BaseModel):
street: str
city: str
zip: str
class User(BaseModel):
id: int
name: str
email: str
active: bool
score: float
address: Address
tags: List[str]
metadata: Optional[str] = None
# Pydantic parses and validates JSON in one step
raw = '{"id":1,"name":"Alice","email":"alice@example.com","active":true,"score":98.5,"address":{"street":"123 Main St","city":"Springfield","zip":"12345"},"tags":["admin","user"],"metadata":null}'
user = User.model_validate_json(raw)
print(user.name) # -> Alice
print(user.model_dump_json()) # -> re-serializes to JSON# Install the generator
pip install datamodel-code-generator
# Generate dataclasses from a JSON file
datamodel-codegen --input data.json --output models.py --output-model-type dataclasses.dataclass
# Generate Pydantic models instead
datamodel-codegen --input data.json --output models.py
# From a JSON string via stdin
echo '{"id": 1, "name": "Alice", "tags": ["admin"]}' | \
datamodel-codegen --output-model-type dataclasses.dataclass
# Output:
# @dataclass
# class Model:
# id: int
# name: str
# tags: List[str]