PureDevTools

JSON to Python Dataclass Generator

Paste JSON, get Python dataclasses — nested objects, Optional fields, frozen/slots/order — copy or download as .py

All processing happens in your browser. No data is sent to any server.

Options

467 characters

4 classes generated · 590 characters

Classes generated: 4Output size: 590 charsDecorators: @dataclass

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:

This tool runs entirely in your browser — your JSON data never leaves your device.

How to Use This Tool

  1. Paste your JSON in the JSON Input textarea (or click Load sample to try an example)
  2. Configure options: root class name, Optional, frozen, slots, order, annotations, helpers
  3. The Python output updates instantly in the Python Output panel
  4. Click Copy to copy to clipboard, or Download .py to save as a .py file

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 valuePython type
"hello"str
42int
3.14float
true / falsebool
nullOptional[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 keyPython field
firstNamefirst_name
isActiveis_active
userIduser_id
Content-Typecontent_type
classclass_ (reserved keyword)
importimport_ (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:

@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:

@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:

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:

  1. Narrow str to Literal for enum-like fields:

    from typing import Literal
    status: Literal["active", "inactive", "pending"]
  2. Use datetime for date fields:

    from datetime import datetime
    created_at: datetime  # after datetime.fromisoformat(data["created_at"])
  3. Replace Optional[Any] with a specific type:

    deleted_at: Optional[str]  # if you know it's a date string or null
  4. Use ClassVar for class-level constants:

    from dataclasses import dataclass
    from typing import ClassVar
    
    @dataclass
    class Config:
        VERSION: ClassVar[str] = "1.0"
        host: str
  5. Combine with Pydantic for validation — copy the field names and types into a Pydantic BaseModel for 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.

Related Tools

More JSON Tools