JSON to Python Dataclass

Generate Python dataclasses from JSON instantly. Supports @dataclass, Pydantic v2 BaseModel, and TypedDict. Handles nested objects, arrays, optional fields, and custom root class names. Free, runs in your browser.

  • Runs in your browser
  • Your data never leaves your browser
  • Free · No Sign-Up
A blank name uses Root. Changing the name generates again after 300 ms.
Mode Choose @dataclass, Pydantic v2 or TypedDict. Changing the mode generates again immediately.
Replace JSON with a sample containing nested objects, arrays and null, then generate immediately with the current settings.
Clear JSON, output and status. Keep the root name and the selected mode. Ctrl/⌘+L with focus in the tool also clears the root name.
Enter valid JSON without comments or trailing commas. Generation runs 300 ms after typing stops; invalid JSON clears the output and shows an error.
Python Output
Copy the complete displayed Python output. Empty output is not copied.
Save the complete displayed output as a .py file. The filename uses the lowercase root name; characters outside ASCII letters, digits and underscores become underscores. Empty output is not downloaded.

Enter JSON or load the example to generate Python.

Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.

Type Mapping

  • null → Optional[Any] = None
  • string → str
  • integer → int
  • float → float
  • boolean → bool
  • array → List[T]
  • mixed array → List[Union[T1, T2]]
  • nested object → separate class

Example

Given this JSON:

{"user": {"first_name": "Alice", "age": 30}, "tags": ["admin"], "note": null}

The tool generates (@dataclass mode):

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

@dataclass
class User:
    first_name: str
    age: int

@dataclass
class Root:
    user: User
    tags: List[str]
    note: Optional[Any] = None

Example: Nested Objects and Missing Keys

Input:

{"id": 7, "title": "Release notes", "author": {"name": "Alice", "email": null}, "tags": ["python", "json"], "score": 4.5, "comments": [{"user": "bob", "text": "nice"}, {"user": "carol"}]}

Output in @dataclass mode:

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

@dataclass
class Author:
  name: str
  email: Optional[Any] = None

@dataclass
class CommentsItem:
  user: str
  text: Optional[str] = None

@dataclass
class Root:
  id: int
  title: str
  author: Author
  tags: List[str]
  score: float
  comments: List[CommentsItem]

Classes are ordered so that each one is defined before it is used. text is missing from the second comment, so it becomes Optional[str] = None.

dataclass, Pydantic or TypedDict

The three modes describe the same shape but behave differently at runtime (checked with Python 3.12 and Pydantic 2.13):

root = Root(**json.loads(raw))
type(root.author)          # <class 'dict'>, not Author
root = Root.model_validate(json.loads(raw))   # Pydantic mode
root.comments[1]           # CommentsItem(user='carol', text=None)
  • @dataclass does not validate or convert. Root(**data) keeps nested objects as plain dicts and accepts wrong types. Use it when the data is already trusted, or convert nested fields yourself.
  • Pydantic validates types and builds nested models; use it for API responses you do not control. model_validate_json(raw) parses and validates in one step.
  • TypedDict only describes dict types for a type checker; nothing is checked at runtime. Every key is required by default, so the tool marks a key that is missing from some items as NotRequired[...] (PEP 655, typing in Python 3.11+, typing_extensions before that). Optional[...] only means the value may be None; the key would still be required.

Example: TypedDict with Missing Keys

Two products where note is null in the first and absent from the second, and discount only appears in the second (root class name Product, TypedDict mode):

[{"id": 1, "sku": "PEN-01", "price": 2, "note": null}, {"id": 2, "sku": "INK-07", "price": 1.5, "discount": 0.1}]
from typing import Any, NotRequired, Optional, TypedDict

class Product(TypedDict):
  id: int
  sku: str
  price: float
  note: NotRequired[Optional[Any]]
  discount: NotRequired[float]

price is 2 in one item and 1.5 in the other; PEP 484 lets an int stand in for a float, so the field is float. At runtime Product.required_keys is {'id', 'sku', 'price'} and optional_keys is {'note', 'discount'} (checked with Python 3.12). A type checker then accepts a product without discount and rejects one without sku (mypy 2.3.1: Missing key “sku” for TypedDict “Product”).

Limits

  • null becomes Optional[Any]; replace Any with the real type.
  • Keys that are not valid Python identifiers (for example user-id or keywords such as class) need renaming, plus Field(alias="user-id") in Pydantic.
  • Dates stay str; Pydantic converts ISO 8601 strings if you change the type to datetime.
  • Arrays of primitives at the root generate no class.

Empty arrays and sample coverage

An empty array gives the generator no evidence about its element type, so {"tags": []} produces tags: List[Any]. Include another object with {"tags": ["admin"]} in the same input array and the merged field becomes List[str]. The generator uses the samples you provide. It cannot infer a field that appears in none of them. Include representative objects with missing keys and null values before copying the classes.

FAQ

What does this tool generate?

It generates Python class definitions from JSON. Choose between standard @dataclass (stdlib), Pydantic v2 BaseModel, or TypedDict. Each nested object becomes its own named class.

What output modes are supported?

Three modes: @dataclass (Python stdlib, default), Pydantic v2 BaseModel, and TypedDict (Python 3.8+; NotRequired needs 3.11+ or typing_extensions).

How are JSON types mapped to Python types?

string → str, integer → int, float → float, boolean → bool, null → Optional[Any], array → List[T], nested object → separate class.

When are fields marked as Optional?

A field is marked Optional[T] = None when its value is null in the JSON sample, or when it is missing in some objects of a merged array.

How are nested objects handled?

Each nested object is extracted into a separate class named after the field key in PascalCase. Child classes are always defined before the parent class so the output is immediately usable.

Is my data sent to a server?

No. The entire conversion runs in your browser. No data leaves your machine.