Code Generators
JSON to Python Converter
Paste a JSON or XML sample — the format is auto-detected — and get typed Python models with names, nesting and nullability inferred for you.
In short
Convert JSON to Python online: paste a sample and generate typed Python models with serialization helpers — powered by quicktype, in your browser.
By NaveenKumar T · Updated
- JSON or XML input, auto-detected
- Nested objects become types
- Nullability inferred
Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →
Example
Example: JSON order payload to Python
A small order document with a nested object, an array of two items, a decimal total and a null field — enough to show how each Python type, list and nullable is inferred. The same page accepts the XML form of this order too, so the sample below is an example rather than the only accepted format. The right-hand side is the exact output of this tool.
{
"id": "ord_9F2KX",
"status": "processing",
"paid": true,
"customer": { "name": "Ada Lovelace", "email": "ada@example.com", "phone": null },
"items": [
{ "sku": "KB-75", "qty": 1, "price": 149.99 },
{ "sku": "MS-12", "qty": 2, "price": 39.5 }
],
"total": 228.99
}from typing import Any, List, TypeVar, Callable, Type, cast
T = TypeVar("T")
def from_str(x: Any) -> str:
assert isinstance(x, str)
return x
def from_none(x: Any) -> Any:
assert x is None
return x
def from_int(x: Any) -> int:
assert isinstance(x, int) and not isinstance(x, bool)
return x
def from_float(x: Any) -> float:
assert isinstance(x, (float, int)) and not isinstance(x, bool)
return float(x)
def to_float(x: Any) -> float:
assert isinstance(x, (int, float))
return x
def from_bool(x: Any) -> bool:
assert isinstance(x, bool)
return x
def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
assert isinstance(x, list)
return [f(y) for y in x]
def to_class(c: Type[T], x: Any) -> dict:
assert isinstance(x, c)
return cast(Any, x).to_dict()
class Customer:
name: str
email: str
phone: None
def __init__(self, name: str, email: str, phone: None) -> None:
self.name = name
self.email = email
self.phone = phone
@staticmethod
def from_dict(obj: Any) -> 'Customer':
assert isinstance(obj, dict)
name = from_str(obj.get("name"))
email = from_str(obj.get("email"))
phone = from_none(obj.get("phone"))
return Customer(name, email, phone)
def to_dict(self) -> dict:
result: dict = {}
result["name"] = from_str(self.name)
result["email"] = from_str(self.email)
result["phone"] = from_none(self.phone)
return result
class Item:
sku: str
qty: int
price: float
def __init__(self, sku: str, qty: int, price: float) -> None:
self.sku = sku
self.qty = qty
self.price = price
@staticmethod
def from_dict(obj: Any) -> 'Item':
assert isinstance(obj, dict)
sku = from_str(obj.get("sku"))
qty = from_int(obj.get("qty"))
price = from_float(obj.get("price"))
return Item(sku, qty, price)
def to_dict(self) -> dict:
result: dict = {}
result["sku"] = from_str(self.sku)
result["qty"] = from_int(self.qty)
result["price"] = to_float(self.price)
return result
class Root:
id: str
status: str
paid: bool
customer: Customer
items: List[Item]
total: float
def __init__(self, id: str, status: str, paid: bool, customer: Customer, items: List[Item], total: float) -> None:
self.id = id
self.status = status
self.paid = paid
self.customer = customer
self.items = items
self.total = total
@staticmethod
def from_dict(obj: Any) -> 'Root':
assert isinstance(obj, dict)
id = from_str(obj.get("id"))
status = from_str(obj.get("status"))
paid = from_bool(obj.get("paid"))
customer = Customer.from_dict(obj.get("customer"))
items = from_list(Item.from_dict, obj.get("items"))
total = from_float(obj.get("total"))
return Root(id, status, paid, customer, items, total)
def to_dict(self) -> dict:
result: dict = {}
result["id"] = from_str(self.id)
result["status"] = from_str(self.status)
result["paid"] = from_bool(self.paid)
result["customer"] = to_class(Customer, self.customer)
result["items"] = from_list(lambda x: to_class(Item, x), self.items)
result["total"] = to_float(self.total)
return result
def root_from_dict(s: Any) -> Root:
return Root.from_dict(s)
def root_to_dict(x: Root) -> Any:
return to_class(Root, x)
Look for the "phone" field: sampled as null, it is typed as None. "items" became List[Item], and "total" is float.
Learn more
From JSON sample to Python types
Hand-writing model classes from a JSON payload is transcription work: read a field, type a property, repeat eighty times, miss one. This page runs quicktype (the same engine behind the best-known generators) against your document, merging array elements to find the common shape and naming nested types from their keys.
The from_dict helpers validate with assert, and python -O strips every assert from the compiled bytecode. Run the models under a normal interpreter, or replace the generated asserts with explicit "if not isinstance(...): raise TypeError" checks before shipping — otherwise a drifted payload passes silently in exactly the environment where the check was supposed to catch it.
How JSON values become Python types
Inference works from the values in your sample. Strings map to str, integers and decimals are told apart (228.99 becomes float, while 1 and 2 stay integral), true/false become the language's boolean, and an object such as "customer" becomes its own named type. The "items" array is typed as List[Item] because every element shares the same keys — quicktype unifies the shapes of all array elements into one Item type.
Nulls are the one place inference needs your help: "phone": null carries no type information, so the field is emitted as None. If the real API sometimes sends a string there, include a sample where the field is populated (paste several documents merged into one array) and the generated type becomes the union of what it saw.
Pasting XML works here too — a sample starting with "<" is parsed before inference runs — but if XML is your usual input, XML to Python is the page written for it: same generator, with the element-versus-attribute typing rules and a worked XML example.
Need models that validate themselves on construction rather than plain classes with a separate from_dict helper? JSON to Pydantic generates pydantic.BaseModel classes from the same kind of sample — the models FastAPI and most modern Python web services already expect.
Annotations, nulls and nested arrays in the generated Python
Python is annotation-free here: quicktype emits plain classes with class-level type hints, an explicit __init__, and from_dict/to_dict staticmethods — no dataclass decorator, no pydantic, no attrs. The real work sits in module-level helpers (from_str, from_int, from_float, from_none, from_list, from_union, to_class) that assert each value's type as they convert, so a drifted payload raises AssertionError at the field that broke rather than deep in your code. Wire names survive inside the helper calls: obj.get("customer-ref") feeds a customer_ref attribute, so PEP 8 naming costs you nothing.
A field sampled only as null is annotated None and converted with from_none, which asserts the value really is None — strict, and wrong the moment the API sends a string. Merge a second document where the field is populated and the hint becomes Optional[str], converted through from_union with both branches listed, which is the honest signature. A key missing from one of the merged samples gets the same Optional treatment plus an is-not-None guard in to_dict, so it is omitted from the output dict instead of being written back as null.
Nested objects become their own classes named from the key — Customer, Item — each with its own from_dict, and the parent calls them explicitly: Customer.from_dict(obj.get("customer")). A list of objects is hinted List[Item] and built with from_list(Item.from_dict, ...), so every element is validated, not just the first. The degenerate arrays are the thing to watch: one element is enough to name the class but not to reveal which fields are optional, and an empty array is hinted List[Any] with no element class generated at all.
Help
Frequently asked questions
Everything you need to know about the JSON to Python.
01How do I generate Python classes from JSON?
Paste a representative document — JSON or XML, the format is detected automatically — and press Convert. A real API response works best. Nested objects become their own Python types, arrays become List[Item], and the result downloads as Root.py.
02What does the generated Python code include?
Python output uses annotated classes with type hints and from_dict/to_dict helpers — modern, mypy-friendly models that make API payloads autocomplete in your editor.
03How do I use the generated Python code in my project?
Nothing to install — the output is standard-library Python 3 (typing plus explicit __init__ constructors). Parse with root_from_dict(json.loads(text)) and serialize with root_to_dict(root); every class also exposes from_dict and to_dict. The helpers assert each value's type as they convert, so a payload that drifts from the sample fails loudly with an AssertionError instead of silently producing a wrong object.
04Does the generated Python require any dependencies?
The output is standard library only — typing, plus datetime and enum where the sample needs them — so nothing extra needs installing. The from_dict helpers do the casting explicitly, so you also get a readable map of how each field converts.
Keep working
Related tools
Learn the format
Related guides
JSON Examples: From Hello World to Real API Payloads
Copy-ready JSON examples: basic objects, arrays, nested structures, API responses, configuration files — each explained line by line.
2 min readGuide · JSONPretty Print JSON in Python: Every Method That Matters
All the ways to pretty print JSON in Python: json.dumps with indent, sort_keys, the python -m json.tool one-liner, files, and Unicode gotchas.
2 min read