What is JSON to Pydantic Model Generator?
Pydantic is the de-facto data-validation layer for modern Python — it powers FastAPI request bodies, validates settings in production services, and turns untrusted JSON into typed, validated Python objects. This generator emits Pydantic v2 `BaseModel` classes, which differ meaningfully from the v1 classes most older tutorials show. In v2 the validation core was rewritten in Rust (pydantic-core), `@validator` became `@field_validator`, `@root_validator` became `@model_validator`, the inner `class Config` gave way to `model_config = ConfigDict(...)`, and `.dict()`/`.json()` were renamed to `.model_dump()`/`.model_dump_json()`. If you paste v1-era decorators into a v2 project you get deprecation warnings or hard errors, so generating v2-correct scaffolding from the start saves real migration pain. Unlike a plain `json-to-python` dataclass generator, the output here is runtime-validating: every field is type-checked, coerced, and error-reported when you call `Model.model_validate(data)`. The generator infers `str`, `int`, `float`, `bool`, nested models, `list[T]`, and `T | None` from your sample, converts camelCase JSON keys to snake_case Python attributes with `Field(alias=...)`, and orders nested models so the file imports cleanly with no forward-reference juggling.
How to Use
- Paste a real API response (not a hand-typed example) so every field gets the type it actually carries at runtime — a numeric string like "42" will be inferred as str, which is usually what you want for IDs
- Set the root class name to match your domain (e.g. "CheckoutRequest" for a FastAPI @app.post body) — this is the class you will pass to model_validate or annotate the endpoint parameter with
- Enable snake_case conversion when your JSON uses camelCase keys: the generator emits snake_case attributes plus Field(alias="originalKey") and you add model_config = ConfigDict(populate_by_name=True) so both forms deserialize
- After generating, attach @field_validator("email") or @computed_field for any business rules — the generator gives you the typed skeleton, you add the v2-style validators on top
- Drop the classes into your FastAPI app and use them directly as request/response models; FastAPI reads the Pydantic schema to produce OpenAPI docs automatically
Why Use This Tool?
Tips & Best Practices
- In v2, migrate @validator to @field_validator and add the @classmethod decorator under it — field_validator does not implicitly make the method a classmethod the way v1 sometimes appeared to
- Use @computed_field with @property for derived values (e.g. full_name from first + last) — it shows up in model_dump() output, unlike a plain @property
- For cross-field checks (password == confirm_password) use @model_validator(mode="after"), which runs on the fully constructed instance; mode="before" runs on the raw dict before field validation
- Set model_config = ConfigDict(extra="forbid") when you want unexpected JSON keys to raise instead of being silently dropped — invaluable for catching typos in client payloads
- For ISO timestamps, annotate with datetime and Pydantic v2 parses the string automatically; you do not need a validator, but you do need to import datetime
- Call .model_validate(data) not the old .parse_obj(), and .model_dump(by_alias=True) to serialize back to the original camelCase keys
Frequently Asked Questions
What is the full JSON type to Pydantic type mapping?
JSON string -> str (or datetime if you annotate it and the string is ISO-8601). JSON integer -> int. JSON float -> float. JSON boolean -> bool. JSON null -> Optional[T] written as T | None. JSON array -> list[T] where T is inferred from the first element. JSON object -> a separate nested BaseModel class. An empty array becomes list[Any]; a heterogeneous array falls back to list[Any] as well.
How do I migrate the generated v2 code if my project is still on Pydantic v1?
Replace model_config = ConfigDict(...) with an inner class Config. Change @field_validator("x") @classmethod back to @validator("x"). Change @model_validator(mode="after") to @root_validator. Replace .model_dump() with .dict() and .model_validate() with .parse_obj(). The field type hints and Field(alias=...) calls are identical between versions, so most of the work is the validators and config.
What replaced @validator and @root_validator in Pydantic v2?
@validator became @field_validator, which validates a single field and must be paired with @classmethod. @root_validator became @model_validator, which validates the whole model and takes a mode argument: mode="before" receives the raw input dict, mode="after" receives the constructed model instance. The old pre=True / always=True keyword arguments are gone — use the mode parameter instead.
When should I use @computed_field?
Use @computed_field (combined with @property) when a value is derived from other fields and you want it included in serialization output. A plain @property is accessible in Python but is excluded from model_dump() and the JSON schema; @computed_field includes it in both, so API consumers see the derived value. It is read-only and recomputed on each access.
Why are camelCase keys converted to snake_case with aliases?
PEP 8 mandates snake_case for Python attributes, but JSON APIs frequently use camelCase. The generator emits snake_case attributes and adds Field(alias="camelCaseKey"). With model_config = ConfigDict(populate_by_name=True), the model accepts both the alias and the Python name on input, and model_dump(by_alias=True) emits the camelCase form on output — so you write idiomatic Python without breaking the wire format.
Is my data sent to a server?
No. All model generation runs in your browser via JavaScript. Your JSON never leaves your device.
Real-world Examples
A FastAPI checkout request body with nested address
You are building a FastAPI POST endpoint and want a validated request model. Pasting the JSON below with snake_case conversion produces a v2 BaseModel pair you can annotate the endpoint with directly; FastAPI then validates the body and documents it in OpenAPI for free.
{
"orderId": "ord_99213",
"customerEmail": "[email protected]",
"totalAmount": 149.95,
"itemCount": 3,
"isGift": false,
"shippingAddress": {
"line1": "742 Evergreen Terrace",
"city": "Springfield",
"postalCode": "62701"
}
}from pydantic import BaseModel, ConfigDict, Field
class ShippingAddress(BaseModel):
line1: str
city: str
postal_code: str = Field(alias="postalCode")
model_config = ConfigDict(populate_by_name=True)
class CheckoutRequest(BaseModel):
order_id: str = Field(alias="orderId")
customer_email: str = Field(alias="customerEmail")
total_amount: float = Field(alias="totalAmount")
item_count: int = Field(alias="itemCount")
is_gift: bool = Field(alias="isGift")
shipping_address: ShippingAddress = Field(alias="shippingAddress")
model_config = ConfigDict(populate_by_name=True)Adding a v2 field_validator after generation
The generator gives you the typed skeleton; you add the business rules. Here a profile model gets a v2 @field_validator to normalize the username and a @model_validator to enforce a cross-field rule — note the @classmethod requirement and the mode="after" instance check that did not exist in v1 the same way.
{
"username": "Jane_Doe",
"age": 30,
"newsletterOptIn": true,
"lastLogin": null
}from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
class Profile(BaseModel):
username: str
age: int
newsletter_opt_in: bool = Field(alias="newsletterOptIn")
last_login: datetime | None = Field(default=None, alias="lastLogin")
model_config = ConfigDict(populate_by_name=True)
@field_validator("username")
@classmethod
def normalize_username(cls, v: str) -> str:
return v.strip().lower()
@model_validator(mode="after")
def check_age(self) -> "Profile":
if self.age < 13:
raise ValueError("user must be at least 13")
return self