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.
What is this for?
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.
When to use it
- LLM structured outputs. OpenAI's
response_formatand Anthropic's tool-use both take a JSON Schema. After you've designed and tested the schema, you usually want a Pydantic model to validate and access fields in Python. - OpenAPI client generation. An OpenAPI spec gives you JSON Schema for each request/response body; this is a quick way to get matching Pydantic models without pulling a full code-generator.
- Schema → Python migrations. You've inherited a system that uses JSON Schema for validation and you want to move it to Pydantic. Paste each schema, get a starting class, refine.
- Quick scaffolding. You sketched the shape in JSON in a notebook; turn it into a real model with one paste.
What this tool handles
type: objectwithproperties+required— generates a nested BaseModel class.type: arraywithitems— generatesList[X].- Primitives:
string→str,integer→int,number→float,boolean→bool,null→None. formaton string:date-time→datetime,email→EmailStr,uri/url→HttpUrl,uuid→UUID.enum→Literal[...];const→Literal[X].oneOf/anyOf→Union[...]; a null variant folds intoOptional[...].type: ["string", "null"]arrays →Optional[str].description→Field(..., description=...).default→ field default.minimum/maximum/minLength/maxLength→Field(ge=..., le=..., min_length=..., max_length=...).- Field names that aren't valid Python identifiers (hyphens, leading digits, keywords) are sanitised, and an
alias=is added to preserve the original wire name. The model is configured withpopulate_by_name=Trueso both work. - Nested objects become nested classes, named after the field if no
titleis provided. $defs/definitionsare emitted as separate classes.
What this tool doesn't handle (yet)
- External
$ref(URL refs). Local refs to$defswork. patternProperties. Emits a TODO comment.additionalPropertieswith a schema. Emits a TODO comment.- Multi-base
allOfcomposition. Single-elementallOfis unwrapped. - Custom validators based on
pattern— emit the field but skip the regex. Add a Pydantic@field_validatorafter pasting if you need it.
Common gotchas
- Pydantic v2 vs v1. Default output is v2 (current). Switch via the dropdown if you're on a v1 codebase. Big differences:
Field(...)for required,model_configreplacesclass Config:, deprecated validator decorators. - Output is a starting point, not the final word. Review it. Especially for complex unions, recursive types, and anything with custom validation rules.
- Names matter. The "Root class name" field controls the top-level class name. Sub-classes are named after their
titleproperty when present, otherwise after the field that contains them. - Required vs Optional in v2. A required field with no default uses
...:name: str = Field(...). Optional fields default toNoneand are wrapped inOptional[T].