JSON to Python: generate dataclasses
Working with json.loads output means dictionary lookups like data["owner"]["name"], no autocompletion and no type checking. This JSON to Python generator turns a sample into @dataclass classes with type hints, so editors and type checkers such as mypy or Pyright understand your data. Nested objects become their own classes and are defined before the classes that use them.
Example
{
"id": 42,
"title": "Write docs",
"done": false,
"priority": 2.5,
"tags": ["docs"],
"owner": { "name": "Ada", "email": null },
"due": "2026-10-01T09:00:00Z",
"subtasks": [
{ "title": "Outline", "estimate": 2 },
{ "title": "Draft" }
]
}
With Types only checked (class name Task):
from dataclasses import dataclass
from typing import Optional, List
from datetime import datetime
@dataclass
class Owner:
name: str
email: None = None
@dataclass
class Subtask:
title: str
estimate: Optional[int] = None
@dataclass
class Task:
id: int
title: str
done: bool
priority: float
tags: List[str]
owner: Owner
due: datetime
subtasks: List[Subtask]
Optional fields get a default of None and appear after required ones, as dataclasses require. Type hints use typing.List and Optional, which work on Python 3.7 and later; on 3.10+ you can modernize them to list[str] and int | None.
With conversion helpers
Dataclasses do not parse nested dictionaries by themselves: Task(**data) would leave owner as a plain dict and due as a string. With Types only off, each class gets a from_dict static method and a to_dict method, plus top-level functions task_from_dict and task_to_dict. They build nested objects, parse dates with dateutil, and assert that each value has the expected type, so malformed data fails loudly:
import json
task = task_from_dict(json.loads(text))
print(task.owner.name, task.due.year)
The helpers need the python-dateutil package when the data contains dates.
Naming
Strings that look like UUIDs are typed as uuid.UUID. JSON keys in camelCase are converted to snake_case attribute names following PEP 8 (isActive becomes is_active), and names that clash with Python keywords or builtins are adjusted (a key class becomes root_class, 2fa becomes the_2_fa). The helper methods map attributes back to the original JSON keys, which is a good reason to keep them when your keys are not already snake_case.
Type mapping
| JSON | Python |
|---|---|
| integer / decimal | int / float |
| string / ISO date | str / datetime |
| boolean | bool |
| array | List[T] |
| object | a dataclass |
| missing or null | Optional[T] = None |
Top-level arrays
If your JSON is a list of records, the generator creates a class for the element, named after the class name with an Element suffix (for example TaskElement), and the helper functions return a List of them. Pasting a list is also the best way to get accurate types, because every record contributes: a key missing from any record becomes Optional, and a field that is an integer in one record and a decimal in another becomes float.
Alternatives
If you use Pydantic, the generated dataclasses are a good starting point: change @dataclass to subclasses of BaseModel and Pydantic will parse nested data and dates itself. For TypedDict-based typing, the same field list applies. Format the output with the Python Formatter, or check the input with the JSON Validator. Converting from XML? Use XML to Python. Generation runs in your browser.