From dicts to typed classes
json.loads gives you nested dicts and lists, which means no autocomplete, no type checking with mypy or Pyright, and KeyErrors at run time. Typed classes fix that, but writing them for a large payload by hand is tedious. Paste an API response, a config file or an event payload here and get class definitions with type hints for every field.
Style: dataclasses or Pydantic v2
The Style option decides what kind of class is generated.
dataclasses (the default) produces @dataclass classes using only the standard library. They describe the data but do not parse it: you build instances yourself, e.g. Address(**data["address"]), and nested objects are not converted automatically. Good for lightweight scripts and when you already validate elsewhere.
Pydantic v2 produces BaseModel subclasses. Root.model_validate(data) parses the whole nested structure, converts nested dicts into model instances and raises a readable error when the data does not match. Choose it for FastAPI apps, settings files and any input you do not control. A top-level array becomes a RootModel, for example class Root(RootModel[List[int]]).
Types and field names
- Objects become classes named after their key (
address→Address, items oforders→Order), and the Root type name option (defaultRoot) names the top-level class. - Whole numbers become
int, values with a decimal point or exponent becomefloat, plusstrandbool. Arrays useList[...]. - Every object in an array is merged into one class. Keys that are missing in some items, or
nullin some, becomeOptional[...] = None; a key that is only evernullis typedNone. - Fields with defaults are placed after required ones, as dataclasses require.
- Keys are turned into snake_case attribute names:
firstNamebecomesfirst_nameandcreated-atbecomescreated_at. Python keywords are prefixed with the class name, soclassbecomesroot_class.
In Pydantic mode every renamed field carries Field(alias="firstName"), so validation reads the original JSON keys. Dataclasses have no alias mechanism: when a key was renamed, map it yourself before constructing the object.
Imports use the typing module (List, Optional), which works on every supported Python 3 version.
Limits
Inference sees only your sample, so strings stay str even when they look like dates, UUIDs or enum values; refine those hints by hand (datetime, UUID, Literal[...]). Mixed-type arrays become Union types. Python integers have arbitrary precision, but the sample is inferred through JavaScript numbers, so an integer beyond 2^53 is flagged with a warning and typed as float; change it back to int. The conversion runs in your browser. Tidy the result with the Python formatter if you change it.
Examples
Customer as dataclasses
Generates Customer, Address and Order dataclasses; firstName becomes first_name and the order note becomes an optional field with a None default.
{
"id": 1042,
"firstName": "Aisha",
"email": "aisha.tan@example.com",
"address": { "city": "Singapore", "postcode": "018956" },
"orders": [
{ "id": "ord_1", "total": 129.9, "note": null },
{ "id": "ord_2", "total": 79 }
]
}from dataclasses import dataclass
from typing import List
@dataclass
class Address:
city: str
postcode: str
@dataclass
class Order:
id: str
total: float
note: None = None
@dataclass
class Customer:
id: int
first_name: str
email: str
address: Address
orders: List[Order]
Webhook payload as Pydantic models
Each renamed key gets Field(alias=…), so WebhookEvent.model_validate(payload) accepts the original event-type and createdAt keys.
{
"event-type": "payment.succeeded",
"createdAt": "2026-09-14T08:21:05Z",
"data": { "amount": 12990, "currency": "SGD", "metadata": { "orderId": "ord_8f2k1" } },
"livemode": false
}from pydantic import BaseModel, Field
class Metadata(BaseModel):
order_id: str = Field(alias="orderId")
class Data(BaseModel):
amount: int
currency: str
metadata: Metadata
class WebhookEvent(BaseModel):
event_type: str = Field(alias="event-type")
created_at: str = Field(alias="createdAt")
data: Data
livemode: bool
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Strings must use double quotes, not single quotesExplained | A Python dict was pasted (for example from print()), not JSON. | Print the data with json.dumps(obj) and paste that instead. |
undefined is not valid JSONExplained | The sample was copied from JavaScript and contains undefined. | Replace undefined with null or remove the key. |
Some integers are larger than 2^53; they are typed as floating-point numbers. Use a 64-bit or big-integer type if you need exact values.Explained | A warning: the sample has very large integers, such as Twitter-style IDs. | Change those annotations to int; Python stores large integers exactly. |
Frequently asked questions
Dataclasses or Pydantic — which should I pick?
Use dataclasses for simple, dependency-free type hints. Use Pydantic when you want parsing and validation of untrusted JSON, especially in FastAPI.
Why did my camelCase keys become snake_case?
Python convention is snake_case for attributes. In Pydantic mode, aliases keep the original JSON names working; with dataclasses, rename the keys when building instances.
Which Python versions does the output support?
It uses typing.List and typing.Optional, so it runs on Python 3.7 and later. Pydantic output needs Pydantic v2.
Is the JSON uploaded?
No. The classes are generated in your browser and nothing is sent to a server.