JSON to Python Dataclass Generator
Paste JSON, get Python dataclasses — nested objects, Optional fields, frozen/slots/order — copy or download as .py
Options
467 characters
4 classes generated · 590 characters
You’re consuming a REST API in Python and want type-safe access to the response fields. The JSON has 25 fields, nested objects, lists of objects, and fields that are sometimes null. You could use dict access everywhere — data["user"]["profile"]["email"] — but one misspelled key means a KeyError at runtime with no IDE autocomplete. A @dataclass with proper type hints gives you autocompletion, mypy checking, and clean attribute access.
Why This Generator (Not the JSON to TypeScript Generator)
PureDevTools has JSON-to-type generators for TypeScript, Go, Rust, and SQL. This tool generates Python @dataclass classes with str, int, float, bool, list[T], Optional[T] types, plus frozen, slots, order options and from_dict()/to_dict() helper methods. Everything runs in your browser; no data is sent anywhere.
What Is a JSON to Python Dataclass Generator?
When building Python applications that consume APIs, read configuration files, or process any JSON data, you need Python types that match the shape of that data. Writing dataclasses by hand is tedious — especially for deeply nested JSON with dozens of fields.
A JSON to Python dataclass generator reads your JSON and automatically produces correct @dataclass definitions, handling:
- Nested objects (each becomes its own named dataclass)
- Arrays of objects (merged into a single dataclass with optional fields for missing keys)
- Primitive values (
str,int,float,bool) - Nullable and missing fields (
Optional[T] = None) - Mixed-type arrays with union annotations
- camelCase JSON keys → snake_case Python field names
This tool runs entirely in your browser — your JSON data never leaves your device.
How to Use This Tool
- Paste your JSON in the JSON Input textarea (or click Load sample to try an example)
- Configure options: root class name, Optional, frozen, slots, order, annotations, helpers
- The Python output updates instantly in the Python Output panel
- Click Copy to copy to clipboard, or Download .py to save as a
.pyfile
Python Dataclasses Explained
Python dataclasses (introduced in Python 3.7 via dataclasses.dataclass) provide a concise way to define data-holding classes without boilerplate __init__, __repr__, and __eq__ methods.
Without dataclasses:
class User:
def __init__(self, id: int, name: str, email: str):
self.id = id
self.name = name
self.email = email
def __repr__(self):
return f"User(id={self.id!r}, name={self.name!r}, email={self.email!r})"
With dataclasses:
from dataclasses import dataclass
@dataclass
class User:
id: int
name: str
email: str
The @dataclass decorator auto-generates __init__, __repr__, and __eq__ — and this generator does the tedious work of writing the class body for you.
Type Mapping: JSON → Python
| JSON value | Python type |
|---|---|
"hello" | str |
42 | int |
3.14 | float |
true / false | bool |
null | Optional[Any] |
[1, 2, 3] | list[int] |
["a", "b"] | list[str] |
[{...}, {...}] | list[ClassName] |
{...} | (named dataclass) |
[] | list[Any] |
Field Naming: camelCase → snake_case
Python convention (PEP 8) mandates snake_case for field names. The generator automatically converts JSON keys:
| JSON key | Python field |
|---|---|
firstName | first_name |
isActive | is_active |
userId | user_id |
Content-Type | content_type |
class | class_ (reserved keyword) |
import | import_ (reserved keyword) |
Options Explained
Root Class Name
The name given to the top-level dataclass. Defaults to Root. If your JSON represents a User object, set the root class name to User for cleaner output.
Optional[T]
When enabled (default), JSON null values and fields missing from some array elements become Optional[T] = None. This is the standard Python pattern for nullable fields:
@dataclass
class Post:
id: int
title: str
published: Optional[bool] = None # missing in some array elements
When disabled, null values become Any without a default value.
frozen
Adds frozen=True to the decorator, making instances immutable. Any attempt to modify a field raises FrozenInstanceError. Useful for:
- API response models that should not be mutated
- Using instances as dictionary keys or set members (requires
frozen=True) - Thread-safe sharing of data between coroutines
@dataclass(frozen=True)
class Config:
host: str
port: int
slots
Adds slots=True (Python 3.10+), which generates __slots__ instead of __dict__ for instances. Benefits:
- Reduced memory usage (~30–40% for small classes)
- Faster attribute access
- Prevents accidental dynamic attribute creation
@dataclass(slots=True)
class Event:
timestamp: int
type: str
payload: str
order
Adds order=True, which generates __lt__, __le__, __gt__, and __ge__ methods. This makes instances comparable and sortable based on field values in declaration order:
@dataclass(order=True)
class Version:
major: int
minor: int
patch: int
versions = [Version(1, 2, 0), Version(1, 0, 3)]
sorted(versions) # [Version(1, 0, 3), Version(1, 2, 0)]
from __future__ import annotations
Adds from __future__ import annotations at the top of the file. This enables PEP 563 (postponed evaluation of annotations), which:
- Allows forward references without quoting class names
- Improves startup performance in Python 3.10+
- Required for
list[T]syntax in Python 3.8 and earlier
Recommended for all generated files targeting Python 3.7–3.9.
from_dict / to_dict
When enabled, each dataclass gets two helper methods:
from_dict(data: dict) — a classmethod for constructing instances from a dictionary:
user = User.from_dict({"id": 1, "name": "Alice", "profile": {"bio": "Engineer"}})
to_dict() — converts the instance back to a plain dictionary:
data = user.to_dict() # {"id": 1, "name": "Alice", "profile": {"bio": "Engineer"}}
Nested dataclasses recursively call their own from_dict/to_dict methods, and lists of dataclasses use list comprehensions.
Handling Nested Objects
Each nested JSON object becomes its own named dataclass. The class name is derived from the parent class name plus the property key in PascalCase:
Input JSON:
{
"id": 1,
"profile": {
"bio": "Engineer",
"social": { "twitter": "@alice" }
}
}
Generated output:
from __future__ import annotations
from dataclasses import dataclass
@dataclass
class RootProfileSocial:
twitter: str
@dataclass
class RootProfile:
bio: str
social: RootProfileSocial
@dataclass
class Root:
id: int
profile: RootProfile
Dependency classes are always defined before the classes that reference them.
Handling Arrays of Objects
When a JSON array contains objects, all objects are merged into a single dataclass. Fields present in only some elements become Optional:
Input JSON:
{
"posts": [
{ "id": 1, "title": "Hello World", "published": true },
{ "id": 2, "title": "Python Tips" }
]
}
Generated output:
from __future__ import annotations
from dataclasses import dataclass
from typing import Optional
@dataclass
class RootPostsItem:
id: int
title: str
published: Optional[bool] = None
@dataclass
class Root:
posts: list[RootPostsItem]
The published field is Optional because it is missing from the second post.
Handling null Values
JSON null maps to Optional[Any] when the Optional option is enabled:
@dataclass
class Root:
name: str
deleted_at: Optional[Any] = None
If you know the actual type of a nullable field (e.g., it should be Optional[str]), update the annotation manually after generation.
Required Fields Before Optional Fields
Python dataclasses require fields with default values to appear after fields without defaults. The generator automatically sorts fields: required fields first, then Optional fields with = None:
@dataclass
class User:
id: int # required
name: str # required
email: Optional[str] = None # optional (after required)
avatar: Optional[str] = None # optional (after required)
Common Use Cases
API Response Typing
Paste the raw JSON from a requests.get(...).json() or a tool like Postman. Use the generated classes to add type safety to your API calls:
import requests
from models import User
data = requests.get("https://api.example.com/users/1").json()
user = User.from_dict(data)
print(user.name)
Configuration Files
If your application reads a JSON configuration file, generate dataclasses from a sample config to catch typos and missing fields:
import json
from models import AppConfig
with open("config.json") as f:
config = AppConfig.from_dict(json.load(f))
Database Record Typing
When using databases that return JSON rows (e.g., PostgreSQL JSON columns, MongoDB documents), generate dataclasses for the row shape.
Third-Party API Integration
Most REST APIs provide sample responses in their documentation. Paste the sample response JSON to instantly get Python dataclasses for the integration.
After Generating: Refining Your Types
The auto-generated types are a starting point. Consider refining them:
-
Narrow
strtoLiteralfor enum-like fields:from typing import Literal status: Literal["active", "inactive", "pending"] -
Use
datetimefor date fields:from datetime import datetime created_at: datetime # after datetime.fromisoformat(data["created_at"]) -
Replace
Optional[Any]with a specific type:deleted_at: Optional[str] # if you know it's a date string or null -
Use
ClassVarfor class-level constants:from dataclasses import dataclass from typing import ClassVar @dataclass class Config: VERSION: ClassVar[str] = "1.0" host: str -
Combine with Pydantic for validation — copy the field names and types into a Pydantic
BaseModelfor runtime validation and JSON serialization.
FAQ
What Python version do I need?
The generated code uses Python 3.7+ syntax (the @dataclass decorator was added in Python 3.7). The list[T] annotation without importing List requires Python 3.9+. The slots=True option requires Python 3.10+. Use from __future__ import annotations for better compatibility in Python 3.7–3.8.
Are the generated dataclasses production-ready?
They are a solid starting point. You may want to refine nullable types, add validators, or integrate with Pydantic for runtime type checking. The generated code is plain Python with no external dependencies.
What if my JSON root is an array?
The generator creates a type alias for the root:
Root = list[RootItem]
And a dataclass for the element type named RootItem.
Can I use these with Pydantic?
Not directly — Pydantic uses BaseModel, not @dataclass (though Pydantic v2 has @pydantic.dataclasses.dataclass). However, you can copy the field names and types to a Pydantic model. The field names and type annotations are identical.
What about deeply nested JSON?
The generator handles arbitrary nesting depth recursively. Each level produces a named dataclass. The order guarantees that leaf classes (no nested references) are always defined before the classes that use them.
Does it handle JSON with comments (JSONC)?
No. Standard JSON.parse does not support comments. Remove comments before pasting, or preprocess the input.