Skip to content
PithLab

↑↓ to move · Enter to open · Esc to close

JSON to Python Dataclass, Pydantic and TypedDict

Turn a JSON sample into Python dataclasses, Pydantic models or TypedDicts.

Use via API

Generate Python classes (dataclasses, Pydantic v2 models or TypedDicts) with type hints from a sample JSON document. Keys become snake_case fields, with aliases where needed. Send JSON, get JSON back.

POST https://pithlab.com/api/v1/tools/json-to-python

curl https://pithlab.com/api/v1/tools/json-to-python \
  -H "Authorization: Bearer $PITHLAB_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"{\"userId\":42,\"name\":\"Ada\",\"isActive\":true,\"tags\":[\"admin\"]}","rootName":"User","style":"pydantic"}'

Fields and responseOpenAPI documentGet an API key

About the JSON to Python

Generate Python dataclasses, Pydantic v2 models or TypedDicts from JSON, with snake_case fields, aliases for renamed keys, Optional types and nested classes.

How to use the JSON to Python

  1. Paste a JSON sample, such as an API response, into the input box.
  2. Choose dataclasses, Pydantic v2 models or TypedDict, and set the root class name.
  3. Nested objects become their own classes, written before the classes that use them.
  4. Copy the code or download it as a .py file.

Examples

Dataclasses with snake_case fields

Input

{"id": 7, "fullName": "Ada Lovelace", "address": {"city": "London", "postCode": "N1"}}

Output

from dataclasses import dataclass


@dataclass
class Address:
    city: str
    post_code: str  # JSON key: "postCode"


@dataclass
class Root:
    id: int
    full_name: str  # JSON key: "fullName"
    address: Address
Pydantic models with aliases and optional fields

Input

{"users": [{"id": 1, "email": null}, {"id": 2, "email": "[email protected]", "isAdmin": true}]}

Output

from typing import Optional

from pydantic import BaseModel, Field


class User(BaseModel):
    id: int
    email: Optional[str]
    is_admin: Optional[bool] = Field(default=None, alias="isAdmin")


class Root(BaseModel):
    users: list[User]
TypedDict with a custom root name

Input

{"sku": "A1", "price": 9.5, "tags": ["new"], "stock": {"warehouse": 3}}

Output

from typing import TypedDict


class Stock(TypedDict):
    warehouse: int


class Product(TypedDict):
    sku: str
    price: float
    tags: list[str]
    stock: Stock

Frequently asked questions

Which Python version does the code need?

Python 3.9 or newer, because lists are written as list[str]. TypedDict output that uses NotRequired needs Python 3.11, or import it from typing_extensions on older versions.

How are renamed keys handled?

Fields are written in snake_case. In Pydantic the original key is kept with Field(alias=...), so model_validate reads the JSON as it is. Dataclasses get a comment naming the JSON key.

Why does TypedDict keep the original key names?

A TypedDict describes the dictionary exactly, so its keys must match the JSON. Keys that are not valid Python names, such as user-agent or class, switch to the TypedDict(...) call form.

When is a field Optional?

A field is Optional when it is null in the sample, or missing from some objects in an array. Missing fields also get a default of None, and dataclass fields with defaults are moved to the end.

How are numbers typed?

Whole numbers become int. If any sample for the field has a fraction or exponent, such as 4.5 or 2.0, the field becomes float.