JSON Schema → Pydantic

Convert JSON Schema to Pydantic v2 model code, in your browser. Paste schema, get a ready-to-paste Python class. Useful for LLM structured-output workflows.

Enter input above to see the result.

From schema to Python model

JSON Schema and Pydantic are the two main ways to describe a structured object — JSON Schema is the lingua-franca for OpenAPI specs, LLM function-calling, and structured outputs; Pydantic is Python's de-facto data-validation library. Pretty often you have one and you need the other. This tool does the conversion in one direction: paste a JSON Schema, get a Pydantic class you can drop into a Python file.

Scenarios that send you here

Type mappings and what gets generated

Unsupported schema features

v1 vs v2 and naming pitfalls

Running the User sample end to end

Load the built-in User sample — id, name, email required, an age with minimum: 0, and a tags array defaulting to [] — and it emits a ready-to-paste Pydantic class. Because email carries "format": "email" it becomes EmailStr; the minimum turns into Field(ge=0); the array becomes List[str] = []; and the three required fields get ... (required) while optional ones default to None. Flip the Pydantic v1/v2 switch and only the details that differ between versions change — e.g. how aliases and config are declared.

Types, unions, nesting, and validation keywords

How are JSON Schema types mapped? integer→int, number→float, string→str, boolean→bool. String formats upgrade the type: date-time→datetime, date→date, email→EmailStr, uri→HttpUrl, uuid→UUID, and the right imports are added automatically.

What happens to enums and unions? An enum becomes Literal[...] of its values; oneOf/anyOf becomes Union[...], and if null is one of the options it collapses to Optional[...]. A type: ["string", "null"] pair also becomes Optional[str].

Does it handle nested objects? Yes — every nested object schema is pulled out into its own BaseModel subclass, emitted before the model that references it so the file is valid Python top-to-bottom. $defs/definitions are generated too.

What about validation keywords and odd field names? minimum/maximum map to ge/le, minLength/maxLength to min_length/max_length, and description flows into Field(description=...). A property name that isn't a valid Python identifier gets a safe name plus an alias (and the matching populate-by-name config). Unsupported bits like patternProperties are marked with a # TODO rather than silently dropped. It all runs in your browser.