Tools · Pydantic

JSON to Pydantic model

Paste JSON and get Pydantic v2 models — one class per nested object, str | None where the sample has null, the root model last so the file imports clean.

no signup · runs entirely in your browser · ⌘V works anywhere on this page

What you get

  • Writes the API-response sample as pydantic v2 · 7 models · 34 fields
  • One class per nested object, children first and the root model last, from __future__ import annotations at the top — the file imports as written
  • str | None where the sample has null, X | None = None where a key is missing from some elements — the paginated list defaults failure_message
  • datetime for an RFC 3339 string (and imports it), int for numbers written whole, float for the rest — 149.00 is a float — bool, list[Item] for a list
  • Keeps a key that is not a Python name through Field(alias=…): class → class_, seat-row → seat_row

What it will not do

  • Write Pydantic v1, dataclasses or TypedDict. v2 models with X | None unions — Python 3.10 or later.
  • Add validators, defaults beyond None, or a model_config. Plain models you extend.
  • Guess a null’s type beyond string: a field that is only ever null is str | None, said so here.
  • Send your text anywhere. The page is static and the engine runs in this tab — open the network panel and watch it stay empty.

What you get

An object → a BaseModel, named from the file
{"id": 1, "status": "paid"}from __future__ import annotations from pydantic import BaseModel class Order(BaseModel): id: int status: str
A key missing in some items → X | None = None
[{"id":1,"note":"x"},{"id":2}]from __future__ import annotations from pydantic import BaseModel class OrderItem(BaseModel): id: int note: str | None = None Order = list[OrderItem]
An RFC 3339 string → datetime, with its import
{"created_at": "2026-04-21T14:32:08Z"}from __future__ import annotations from datetime import datetime from pydantic import BaseModel class Order(BaseModel): created_at: datetime
A key that is not a Python name → Field(alias=…)
{"class": "economy", "seat-row": 12}from __future__ import annotations from pydantic import BaseModel, Field class Order(BaseModel): class_: str = Field(alias="class") seat_row: int = Field(alias="seat-row")

The sample

What the first sample opens — a real file, not an illustration written for this page.

clean-order-example.json → Pydantic, as Convert writes it — pydantic v2 · 7 models · 34 fields · 933 b
from __future__ import annotations

from datetime import datetime
from pydantic import BaseModel


class Customer(BaseModel):
    id: str
    email: str
    name: str
    verified: bool
    loyalty_tier: str
…

in VS Code

Convert, then Pydantic — the models land in a new .py editor beside the JSON.

unstringify for VS Code14-day trial · Free and Pro

Questions

Pydantic v1 or v2?

v2. The models use X | None unions and Field(alias=…), which v2 reads as written; nothing here needs a validator import.

Why is the root model last?

Each class lands after the ones it names, so the root — which names them all — comes last. With from __future__ import annotations the order would not break, but a file that reads top-down needs no explaining.

What happens when a field is only ever null?

It is str | None. A lone null says nothing about the value, so this is the one guess the models make — and they guess str.

Try it on the file that broke your afternoon.

free · no signup