JSON to Python
Generate dataclass, Pydantic or TypedDict models from a JSON sample — with field names that actually line up with the keys.
Field names stay identical to the JSON keys
This is the one design decision that matters most in Python. Plenty of generators rewrite
isActive to is_active because it reads better — and then
Root(**data) fails with unexpected keyword argument, because Python
has no annotation mechanism to put the key back.
So the generator keeps the key verbatim whenever it is already a legal Python identifier. Only
a name Python cannot parse (first-name, user id) or one that would
break the class itself (class → class_, self →
self_) is transliterated.
import json
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class Root:
id: int
isActive: bool
class_: int
tags: List[str]
website: Optional[str] = None
payload = Root(**json.loads(body)) # works, because the names match Three output styles
| Style | Use it when | Runtime cost |
|---|---|---|
dataclasses | You just want typed attributes. Standard library only — no dependency to install. | None |
Pydantic BaseModel | You are parsing untrusted input and want coercion plus validation errors. | Requires pydantic |
TypedDict | You want static type checking without constructing objects at all — the payload stays a plain dict. | None, but no runtime validation |
Type mapping
| JSON value | Python type |
|---|---|
| whole number | int |
| decimal number | float |
true / false | bool |
| string | str |
| array | List[T] |
| object | its own class |
null | Optional[T] = None |
| key missing from a sibling | Optional[T] = None |
| mixed array | Union[A, B] |
Optional fields are sorted last, on purpose
A dataclass field with a default cannot be followed by one without — Python raises
TypeError: non-default argument follows default argument. The generator therefore
reorders every class so required fields come first and optional ones follow, whatever order
the keys appeared in your sample. Classes themselves are also emitted leaf-first, so a nested
type is always defined before the class that annotates it.
Edge cases worth knowing
-
selfandclsare treated as reserved. A field with either name would producedef __init__(self, self), which is a syntax error at runtime — so they are suffixed instead. -
Optional[Any]is skipped.Anyalready includesNone, so wrapping it adds noise and no information. - Mixed arrays become
Union.[1, "two"]yieldsUnion[int, str]rather than collapsing toAny, which keeps mypy useful. - TypedDict optional keys use
NotRequired[...], which needs Python 3.11 ortyping_extensions.
FAQ
dataclass or Pydantic?
Use a dataclass when you trust the payload and want zero dependencies. Use Pydantic when the JSON comes from outside your system: it coerces "42" to 42 and reports which field was wrong instead of failing somewhere deeper.
Will the dataclass convert nested dicts into objects?
No — a plain @dataclass does not recurse. The nested value stays a dict unless you construct the child class yourself, or use Pydantic, which does recurse automatically.
Do I need from __future__ import annotations?
No. Types are emitted in dependency order, so every referenced class is already defined when its annotation is evaluated.
Is my JSON uploaded?
No. The whole generator runs client-side in this tab.