JSON to Python
The result appears here.
Generate
Your document never leaves the browser.
Pydantic models, dataclasses or TypedDicts from JSON — in your browser, never uploaded.
Paste a payload and get Python 3.11 classes that parse it. The default is Pydantic v2, which validates as it reads; a dataclass or a TypedDict is one choice away for code that has no Pydantic.
Every object in the document becomes a BaseModel subclass, the nested ones first, so each class is defined before a later one refers to it. qty holds whole numbers only, so it is int; price holds 3.5 and 12, so it is float. The file opens with a comment naming the Python version and the pydantic>=2 requirement.
gift-wrap cannot be a Python attribute, so the field is gift_wrap with Field(alias="gift-wrap"), and the model gains populate_by_name=True so your own code can build it with either spelling. It is missing from one line item, so it defaults to None. note is in both, once null, so it is str | None with no default: the key must be there, though it may be null.
The sample, an order with two line items, pasted as the source
{
"order_id": 1042,
"placed_at": "2026-09-25T10:15:00Z",
"paid": true,
"customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
"items": [
{ "sku": "PEN-01", "qty": 2, "price": 3.5, "note": null },
{ "sku": "INK-07", "qty": 1, "price": 12, "note": "Fragile", "gift-wrap": true }
]
}The models written for it, in the default Pydantic v2 style
# Generated by myjsoneditor.com — Python 3.11+
# Requires pydantic>=2
from pydantic import BaseModel, ConfigDict, Field
class Customer(BaseModel):
name: str
email: str
class Item(BaseModel):
model_config = ConfigDict(populate_by_name=True)
sku: str
qty: int
price: float
note: str | None
gift_wrap: bool | None = Field(default=None, alias="gift-wrap")
class Root(BaseModel):
order_id: int
placed_at: str
paid: bool
customer: Customer
items: list[Item]The sample, with Style dataclass
# Generated by myjsoneditor.com — Python 3.11+
# Dataclasses do not turn nested dicts into classes, and cannot tell a null
# field from a missing one: use the Pydantic style when either matters.
# Keys that are not Python names are renamed (see "JSON key"), so
# Class(**data) does not work for those classes.
from dataclasses import dataclass
@dataclass(kw_only=True)
class Customer:
name: str
email: str
@dataclass(kw_only=True)
class Item:
sku: str
qty: int
price: float
note: str | None
gift_wrap: bool | None = None # JSON key: "gift-wrap"
@dataclass(kw_only=True)
class Root:
order_id: int
placed_at: str
paid: bool
customer: Customer
items: list[Item]Style
Pydantic v2, the default: BaseModel classes that validate types and turn nested dicts into nested models when you call model_validate_json.
Style
dataclass: plain @dataclass(kw_only=True) classes from the standard library. The header warns that dataclasses neither convert nested dicts into classes nor tell a null field from a missing one.
Style
TypedDict: type hints over the dicts json.loads already returns, with NotRequired marking a key some records lack. Nothing is checked at run time; a type checker such as mypy or Pyright does the checking.
A key that is a Python keyword gets a trailing underscore, so class becomes class_, and a key starting with a digit gets a prefix, so 2fa becomes field_2fa. In the Pydantic style each renamed field keeps its JSON name as an alias, so reading and writing the document still use the original keys.
An array of mixed values is typed as a union of what was seen, list[str | int] for strings and integers side by side. Timestamps stay str; convert them with datetime.fromisoformat, or change the annotation to datetime and let Pydantic parse them.
A keyword, a key starting with a digit, and a mixed list
{ "class": "A", "2fa": true, "ids": ["a", 1] }Each renamed field keeps its JSON name as an alias
# Generated by myjsoneditor.com — Python 3.11+
# Requires pydantic>=2
from pydantic import BaseModel, ConfigDict, Field
class Root(BaseModel):
model_config = ConfigDict(populate_by_name=True)
class_: str = Field(alias="class")
field_2fa: bool = Field(alias="2fa")
ids: list[str | int]Inference and code generation both run inside this browser tab. The sample is never uploaded, stored on a server or logged, because the page has no server to send it to, and once loaded it carries on working with the connection off.
Python 3.11 or later, as the header comment says. NotRequired, which the TypedDict style uses, joined the standard typing module in 3.11.
No. The models use names only v2 has, such as ConfigDict and model_config. The dataclass and TypedDict styles need no Pydantic at all.
Call Root.model_validate_json(text), with your root class in place of Root. It checks every field and returns nested model instances.