Working with an API that returns JSON? Instead of writing Python classes by hand and guessing field types from the docs, paste the response and get typed data classes generated instantly.

Generate Python dataclasses from JSON →

Why Typed Python Classes Matter

The old pattern of using raw dictionaries for API responses is fragile:

# Dictionary access — no type hints, no autocomplete, runtime KeyError risks
user = response.json()
print(user['profile']['name'])   # What if 'profile' is None?
print(user['age'] + 1)           # What if 'age' is a string?

Python dataclasses, Pydantic models, and TypedDict all solve this by giving you:

  • Autocomplete in IDEs
  • Type checker support (mypy, pyright)
  • Clear documentation of data shape
  • Explicit handling of optional fields

Three Output Modes

The tool supports three output formats, each suited to a different use case.

@dataclass (stdlib, default)

Standard library, no dependencies. Best for internal data structures, configuration, and when you want zero overhead:

from dataclasses import dataclass
from typing import List, Optional, Any

@dataclass
class Address:
    street: str
    city: str
    zip_code: Optional[str] = None

@dataclass
class User:
    id: int
    name: str
    email: str
    address: Address
    tags: List[str]
    avatar: Optional[Any] = None

Pydantic v2 BaseModel

Best for API validation, settings management, and anywhere you need runtime validation plus serialization. Pydantic is the standard choice for FastAPI applications:

from pydantic import BaseModel
from typing import List, Optional, Any

class Address(BaseModel):
    street: str
    city: str
    zip_code: Optional[str] = None

class User(BaseModel):
    id: int
    name: str
    email: str
    address: Address
    tags: List[str]
    avatar: Optional[Any] = None

With Pydantic, you get validation on instantiation, .model_dump() for serialization, and .model_validate() for parsing dictionaries.

TypedDict (Python 3.8+)

Best for type-checking dictionaries without changing their runtime behavior. Useful when working with libraries that expect plain dicts:

from typing import List, Optional, Any, TypedDict

class Address(TypedDict):
    street: str
    city: str
    zip_code: Optional[str]

class User(TypedDict):
    id: int
    name: str
    email: str
    address: Address
    tags: List[str]
    avatar: Optional[Any]

JSON Type to Python Type Mapping

JSONPython
"string"str
42int
3.14float
true / falsebool
nullOptional[Any] = None
["a", "b"]List[str]
[1, "a", true] mixedList[Union[int, str, bool]]
{} nested objectseparate class

How Nested Objects Are Handled

Each nested object becomes its own named class in PascalCase, derived from the field name. Classes are always output in dependency order — children before parents — so the generated code is immediately usable without rearranging:

Input JSON:

{
  "user": {
    "profile": {
      "bio": "Developer",
      "location": "Berlin"
    },
    "name": "Alice",
    "age": 30
  },
  "timestamp": 1713456789
}

Generated @dataclass:

from dataclasses import dataclass
from typing import Any

@dataclass
class Profile:
    bio: str
    location: str

@dataclass
class User:
    profile: Profile
    name: str
    age: int

@dataclass
class Root:
    user: User
    timestamp: int

Optional Fields and Nullable Values

A field is marked Optional when:

  1. Its value is null in the sample JSON
  2. It is absent in some objects within a JSON array
# JSON: {"score": null, "grade": "A"}
# score is null → Optional[Any] = None

@dataclass
class Result:
    grade: str
    score: Optional[Any] = None

When processing arrays of objects, the tool merges all fields from all items. Fields that only appear in some items become Optional.

Working with API Responses

FastAPI + Pydantic

The most common use case is parsing FastAPI endpoint responses:

import httpx
from pydantic import BaseModel
from typing import List

class Post(BaseModel):
    id: int
    title: str
    body: str
    userId: int

class Comment(BaseModel):
    postId: int
    id: int
    name: str
    email: str
    body: str

# Parse API response into typed models
async with httpx.AsyncClient() as client:
    resp = await client.get('https://api.example.com/posts/1')
    post = Post.model_validate(resp.json())
    print(post.title)  # fully typed

Standard @dataclass with dacite

If you prefer stdlib dataclasses but still want dict → dataclass conversion:

from dacite import from_dict
from dataclasses import dataclass

@dataclass
class User:
    id: int
    name: str
    email: str

data = {"id": 1, "name": "Alice", "email": "[email protected]"}
user = from_dict(User, data)
print(user.name)  # Alice

TypedDict with json.loads

For zero-overhead type checking of JSON data:

import json
from typing import TypedDict, cast

class Config(TypedDict):
    host: str
    port: int
    debug: bool

with open('config.json') as f:
    config: Config = cast(Config, json.load(f))
    print(config['host'])  # type-checked by mypy/pyright

Customizing the Root Class Name

By default the top-level class is named Root. Change it to match your domain:

  • API response → ApiResponse, SearchResult, UserProfile
  • Configuration file → AppConfig, DatabaseConfig
  • Webhook payload → WebhookEvent, PaymentNotification

The tool propagates your root class name through the output consistently.

Limitations to Know

JSON is a sample, not a schema. If a field can be multiple types in practice, the tool only sees the type in your sample. Always review Optional fields and union types before production use.

Naming comes from field keys. The tool converts snake_case, camelCase, and kebab-case JSON keys to PascalCase class names. Unusual naming patterns may produce unexpected class names — rename in the output as needed.

Deep nesting creates many classes. Deeply nested JSON produces a class hierarchy of the same depth. This is correct behavior, not a bug.


Paste your JSON and pick your output format. Open the JSON to Python Dataclass generator →