Hand-writing Pydantic models from a large JSON payload is mechanical work: map types, nest classes, repeat. I've been using a free JSON to Pydantic Converter from AabiTech to skip that step. Here's what it does and where you still need to think.
What it does
Paste JSON (or upload a file, up to 5 MB) and get Python model code back.
- Nested objects become separate models, and arrays of objects become
list[Model] - Pydantic v2 or v1 compatibility mode
- Configurable root model name
- 2, 4, or 8 space indentation
- Copy to clipboard or download as
.py - Runs client-side; the page states your JSON is processed in the browser and generated code is never executed
No signup required.
Example
Input:
{
"name": "Ayesha",
"age": 25,
"active": true
}
Output:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
active: bool
With nested payloads, you get one class per object, referenced from the parent. That's where it saves the most time.
v1 vs v2: pick the right mode
The two versions differ enough that wrong-version output will bite you:
| Pydantic v1 | Pydantic v2 | |
|---|---|---|
| Parse a dict | Model.parse_obj(d) |
Model.model_validate(d) |
| Serialize | m.dict() |
m.model_dump() |
| Config | class Config: |
model_config = ConfigDict(...) |
Select the mode matching your installed version, then verify imports and config anyway.
What a single sample can't tell you
Generated models are inferred from one example, so review these before shipping:
1. Optional vs nullable. These are different things.
a: str | None # required, but may be None
b: str | None = None # may be omitted, may be None
A sample with "b": null doesn't tell you whether b can be absent. Check more records.
2. Mixed types. If a field is int in some records and str in others, you need a union or a validator:
id: int | str
3. Key naming. firstName, user-id, or keys with spaces need Python-safe attribute names plus aliases:
from pydantic import BaseModel, Field
class User(BaseModel):
first_name: str = Field(alias="firstName")
Check alias and serialization settings (by_alias=True on dump) before wiring this to an external API.
4. Empty arrays. [] gives no item type to infer from. Fill it in manually.
5. Constraints. No sample will tell you about min_length, regex patterns, enums, or ranges. Add them yourself.
Suggested workflow
- Validate your JSON first (the site also has a JSON Formatter)
- Use a representative sample, ideally the most complete record you have
- Generate with the right Pydantic version
- Fix optionals, unions, and aliases
- Add validators and constraints
- Test against both valid and invalid payloads
Plugged into FastAPI, the result gives you request validation and OpenAPI docs almost immediately:
@app.post("/users")
async def create_user(user: User):
return user
Privacy note
Even though processing happens in the browser, keep tokens, passwords, and real customer data out of sample payloads. Good habit for any online tool.
Try it
aabitech.com/tools/json-to-pydantic-converter
Treat the output as a solid first draft, not a finished schema. How do you handle messy third-party API responses? Share your approach in the comments.
Top comments (0)