JSON to Python Converter
Generate Python classes from JSON data. Supports dataclasses, Pydantic, and TypedDict:
Generate Python Classes from JSON
This tool converts JSON data into type-annotated Python classes. Choose from dataclasses, Pydantic models, or TypedDict depending on your use case.
Output Formats
dataclass (Python 3.7+)
Standard library solution for data classes. Simple, no dependencies:
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class User:
id: int
user_name: str
email: str
tags: List[str]
profile: Optional[Profile] = NonePydantic
Powerful data validation library, popular with FastAPI:
from pydantic import BaseModel, Field
from typing import List, Optional
class User(BaseModel):
id: int
user_name: str = Field(..., alias="userName")
email: str
tags: List[str]
class Config:
populate_by_name = TrueTypedDict
Type hints for dictionaries, useful for type checking without runtime overhead:
from typing import TypedDict, List
class User(TypedDict):
id: int
user_name: str
email: str
tags: List[str]When to Use Each Format
| Format | Best For | Features |
|---|---|---|
| dataclass | General purpose, no deps | Auto __init__, __repr__, __eq__ |
| Pydantic | API validation, FastAPI | Validation, serialization, aliases |
| TypedDict | Type checking only | Dict compatibility, no overhead |
Options Explained
snake_case conversion
Converts camelCase JSON keys to Python's preferred snake_case:
// JSON: "firstName"
# Python: first_nameFor Pydantic, this adds Field(alias="...") to map between formats.
Optional for nulls
When enabled, null values become Optional[T] with a default of None.
Type Mapping
| JSON | Python |
|---|---|
| string | str |
| integer | int |
| float | float |
| boolean | bool |
| null | Optional[T] or None |
| array | List[T] |
| object | Nested class |
Using Generated Classes
With dataclass
import json
# Parse JSON
data = json.loads(json_string)
user = User(**data)
# Access fields
print(user.user_name)
# Convert back to dict
from dataclasses import asdict
user_dict = asdict(user)With Pydantic
# Parse JSON directly
user = User.model_validate_json(json_string)
# Or from dict
user = User(**data)
# Convert to JSON
json_output = user.model_dump_json()
# With aliases (original JSON keys)
json_output = user.model_dump_json(by_alias=True)Working with APIs
For comprehensive JSON handling in Python, see our Python JSON Guide which covers parsing, serialization, and common patterns.
Related Tools
- Python JSON Guide — Complete guide to JSON in Python
- JSON Validator — Validate JSON before converting
- JSON to Java — Generate Java POJOs
- JSON to TypeScript — Generate TS interfaces
- JSON Schema Generator — Create schema from data
Frequently Asked Questions
Should I use dataclass or Pydantic?
Use dataclass for simple data containers without validation needs. Use Pydantic when you need validation, serialization, or are building APIs with FastAPI. Pydantic adds ~2ms overhead per parse but catches errors early.
What Python version do I need?
Dataclasses require Python 3.7+. Pydantic v2 requires Python 3.8+. TypedDict requires Python 3.8+ (or typing_extensions for 3.7).
How do I handle nested objects?
The converter automatically generates separate classes for nested objects and uses them as type annotations. Dependencies are ordered correctly in the output.
Common Mistakes & Pro Tips
- dataclass vs TypedDict vs dict are different tools — A `@dataclass` gives you a real class with `__init__`, attribute access (`obj.name`), and defaults; a `TypedDict` is just a type annotation over a plain `dict` (`obj["name"]`) with no runtime behavior; a raw `dict` has no typing at all. Choose dataclass when you instantiate objects, TypedDict when you're typing JSON you `json.loads` and access by key.
- json.loads gives float, not int, for decimals — Python's `json` maps integers to `int` and any number with a decimal point or exponent to `float`. A sample value of `1.0` is inferred as `float`, while `1` is `int` — so if a field is sometimes whole and sometimes fractional, annotate it `float`. Use `parse_int`/`parse_float` hooks or `Decimal` if you need exact decimals (e.g. money).
- Optional needs a default to actually be optional — `Optional[str]` (i.e. `str | None`) only documents that the value may be `None`; it does not make the dataclass field optional. To allow omitting it you must give a default, like `name: Optional[str] = None`. Note that mutable defaults (lists, dicts) require `field(default_factory=list)`, never `= []`.
- Reserved words and bad identifiers can't be field names — JSON keys like `class`, `from`, `import`, `lambda`, or keys with hyphens/spaces are invalid Python identifiers. For dataclasses you'll need to rename them (e.g. `class_` ) and remap during loading; TypedDict can use the functional form `Movie = TypedDict('Movie', {'class': str})` to keep the literal key.
- Empty arrays and mixed arrays degrade to broad types — An empty array `[]` carries no element type, so it's typed `List[Any]`; a heterogeneous array becomes `List[Any]` or a `Union`. Tighten these by hand to the real element type, e.g. `List[int]`, once you know the schema.
Frequently Asked Questions
How do I handle optional or nullable fields?
Type the field as `Optional[T]` (equivalently `T | None` on Python 3.10+) and give it a default of `None` so it can be omitted: `email: Optional[str] = None`. For a TypedDict, mark individual keys with `NotRequired[T]` (Python 3.11+ / typing_extensions) or split into a second `total=False` TypedDict. Remember `Optional` alone doesn't make a dataclass field skippable — the default does.
Do dataclasses validate types at runtime?
No — dataclasses store whatever you pass; type hints are not enforced, so `User(age="oops")` succeeds. If you want runtime validation and JSON parsing/coercion, use Pydantic (`BaseModel`), which checks and converts types, or add `__post_init__` checks manually. The standard `dataclasses` module is purely structural.
How do I convert the generated dataclass back to and from JSON?
`dataclasses.asdict(obj)` gives a dict you can pass to `json.dumps`. Going the other way, `MyClass(**json.loads(text))` works only for flat objects — nested dataclasses won't be reconstructed automatically. For nested structures use `pydantic`, `dacite`, or the `dataclasses-json` library, which rebuild the object tree for you.
Why are my JSON `snake_case` keys kept as-is?
Python's convention is already `snake_case`, so keys like `created_at` map cleanly to attributes without renaming. If your JSON uses `camelCase` (e.g. `createdAt`), the generator keeps that as the attribute name, which is unidiomatic — rename to `created_at` and use an alias (Pydantic `Field(alias=...)` or a custom decoder) to map back to the original JSON key.
Should I use `List`/`Dict` or `list`/`dict` in annotations?
Since Python 3.9 you can subscript the builtins directly (`list[str]`, `dict[str, int]`) and no longer need to import from `typing`. On 3.8 and earlier you must use `typing.List` / `typing.Dict`. Pick based on your minimum supported Python version; the builtins are now preferred.
Does this tool send my JSON anywhere?
No. Conversion happens locally in your browser, so the JSON you paste — including private payloads — is never transmitted to a server. You can use it offline once the page has loaded.