Skip to content

datamodel-code-generator

πŸš€ Generate Python data models from schema definitions in seconds.

Getting Started Open Playground Lead maintainer available for work

PyPI version Conda-forge Downloads PyPI - Python Version codecov license Pydantic v2


✨ What it does

Schema files, raw data, and existing Python models flow through datamodel-code-generator into Python model output types Schema files, raw data, and existing Python models flow through datamodel-code-generator into Python model output types

Pick any one of the supported inputs and pick the Python model style you want as output. --input-model path/to/file.py:ClassName can even retarget an existing Pydantic, dataclass, or TypedDict class defined in another Python file to a different output type.

  • πŸ“„ Converts OpenAPI 3, AsyncAPI, JSON Schema, Apache Avro, XML Schema, Protocol Buffers/gRPC, GraphQL, MCP tool schemas, and raw data (JSON/YAML/CSV) into Python models
  • 🐍 Generates from existing Python types (Pydantic, dataclass, TypedDict) via --input-model
  • 🎯 Generates Pydantic v2, Pydantic v2 dataclass, dataclasses, TypedDict, or msgspec output
  • πŸ”— Handles complex schemas: $ref, allOf, oneOf, anyOf, enums, and nested types
  • βœ… Produces type-safe, validated code ready for your IDE and type checker

πŸ§ͺ Try It In Your Browser

Generate models in your browser without installing anything.

Playground privacy

Generation runs locally in your browser with Pyodide. Your schema and options are not sent to a backend. Shared repro URLs encode them in the URL fragment (#state=...), which browsers do not send to the server; the full URL can still be stored in your browser history or wherever you share it.


πŸš€ Start Here

Install the CLI and generate your first model from Getting Started.

Default output model

When --output-model-type is omitted, datamodel-code-generator generates Pydantic v2 BaseModel output (pydantic_v2.BaseModel). Use --output-model-type explicitly when you want dataclasses, TypedDict, or msgspec output.


πŸ“₯ Choose Your Input

Input Type File Types Example
πŸ“˜ OpenAPI 3.0/3.1/3.2 .yaml, .json API specifications
πŸ“‘ AsyncAPI .yaml, .json Event-driven API specifications
πŸ“‹ JSON Schema .json, .yaml Data validation schemas
πŸͺΆ Apache Avro .avsc, .json Avro schemas
🧾 XML Schema .xsd XML document schemas
🧩 Protocol Buffers / gRPC .proto Protobuf messages and service schemas
πŸ”· GraphQL .graphql GraphQL type definitions
πŸ› οΈ MCP Tool Schemas .json, .yaml MCP tool input/output schemas
πŸ“Š JSON/YAML/CSV Data .json, .yaml, .csv Infer schema from data
🐍 Python Models .py Pydantic, dataclass, TypedDict

βœ… Conformance Signals

CI exercises datamodel-code-generator against pinned external corpora for XML Schema, JSON Schema, AsyncAPI, Apache Avro, and Protocol Buffers. See the Conformance Dashboard for the generated summary of runner scripts, tox environments, CI jobs, expected corpus counts, and upstream sources.


πŸ“€ Choose Your Output

# πŸ†• Pydantic v2 (recommended for new projects)
datamodel-codegen --output-model-type pydantic_v2.BaseModel ...

# πŸ—οΈ Python dataclasses
datamodel-codegen --output-model-type dataclasses.dataclass ...

# πŸ“ TypedDict (for type hints without validation)
datamodel-codegen --output-model-type typing.TypedDict ...

# ⚑ msgspec (high-performance serialization)
datamodel-codegen --output-model-type msgspec.Struct ...

See Supported Data Types for the full list.


🌐 Generate a FastAPI server or an HTTP client (experimental)

Experimental

Server and client generation are experimental since 0.84.0: their options and generated packages may change. See Experimental Features.

From one OpenAPI document, --generate-server fastapi writes a FastAPI server package and --generate-client httpx2 an HTTPX2 client package, in the same run as the models. The models stay the runtime contract: routes and client methods take and return the generated models, so the server and the client parse and produce the same classes you already use. Every generated file is regenerated on each run; keep your own code outside the generated packages. The commands put everything in one application package, app: the generated app/models.py, app/server/, and app/client/, and your app/services/, so no generic top-level name such as models or server is taken.

This example is the FastAPI server tutorial, and the tests of this project run it as shown.

Input (openapi.yaml)
openapi: 3.1.0
info:
  title: Pets
  version: "1.0"
servers:
  - url: http://localhost:8000
paths:
  /pets:
    get:
      operationId: listPets
      tags: [pets]
      parameters:
        - name: limit
          in: query
          schema: {type: integer, minimum: 1, maximum: 100, default: 20}
      responses:
        "200":
          description: The pets.
          content:
            application/json:
              schema: {$ref: "#/components/schemas/Pets"}
    post:
      operationId: createPet
      tags: [pets]
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: "#/components/schemas/NewPet"}
      responses:
        "201":
          description: Created.
          content:
            application/json:
              schema: {$ref: "#/components/schemas/Pet"}
  /pets/{petId}:
    get:
      operationId: getPet
      tags: [pets]
      parameters:
        - name: petId
          in: path
          required: true
          schema: {type: integer}
      responses:
        "200":
          description: The pet.
          content:
            application/json:
              schema: {$ref: "#/components/schemas/Pet"}
        "404":
          description: No pet has this ID.
          content:
            application/json:
              schema: {$ref: "#/components/schemas/Error"}
components:
  schemas:
    NewPet:
      type: object
      required: [name]
      properties:
        name: {type: string}
        tag: {type: string}
    Pet:
      type: object
      required: [id, name]
      properties:
        id: {type: integer}
        name: {type: string}
        tag: {type: string}
    Pets:
      type: array
      items: {$ref: "#/components/schemas/Pet"}
    Error:
      type: object
      required: [message]
      properties:
        message: {type: string}

Commands

# The application package app, which the generated packages go into
mkdir -p app && touch app/__init__.py

# FastAPI server package in app/server/
datamodel-codegen \
  --input openapi.yaml \
  --input-file-type openapi \
  --openapi-scopes schemas api \
  --output-model-type pydantic_v2.BaseModel \
  --preset standard-py312-20260909 \
  --output app/models.py \
  --generate-server fastapi \
  --server-output app/server \
  --server-package app.server \
  --server-model-package app.models

# HTTPX2 client package in app/client/
datamodel-codegen \
  --input openapi.yaml \
  --input-file-type openapi \
  --openapi-scopes schemas api \
  --output-model-type pydantic_v2.BaseModel \
  --preset standard-py312-20260909 \
  --output app/models.py \
  --generate-client httpx2 \
  --client-output app/client \
  --client-package app.client \
  --client-model-package app.models

--openapi-scopes must include api, and both need Python 3.11 or later, to run and as the target version (the preset sets 3.12); left unset, the run sets them and says how. Each run ends by printing the runtime dependencies of its package to stderr:

Add the runtime dependencies of app.server to your project:
  uv add "fastapi>=0.141.1" "pydantic>=2.14.0" "typing-extensions>=4.16"
Next steps: implement the stubs in app/services/pets.py, then run the server:
  uv add uvicorn && uv run uvicorn app.server.main:app --reload
or: uv add "fastapi[standard]" && uv run fastapi dev --entrypoint app.server.main:app
See app/server/README.md.
Add the runtime dependencies of app.client to your project:
  uv add "httpx2>=2.13.0" "typing-extensions>=4.16" "pydantic>=2.14.0"
Next steps: call the API with the client:
  from app.client import Client

  with Client(base_url=...) as client:
      client.pets.list_pets(...)
See app/client/README.md.

Generated files (trimmed)

app/
β”œβ”€β”€ __init__.py
β”œβ”€β”€ models.py
β”œβ”€β”€ server/
β”œβ”€β”€ services/
└── client/

Implement the server in app/services/pets.py, which generation wrote once with stubs, by replacing the stubs of the Pets class that subclasses the generated service Protocol; type checkers report a missing method or a mismatched signature:

from app import models
from app.server import HTTPResult
from app.server.services import PetsService


class Pets(PetsService):
    def __init__(self) -> None:
        self.pets: dict[int, models.Pet] = {}

    def list_pets(self, *, limit: int) -> models.Pets:
        return models.Pets(list(self.pets.values())[:limit])

    def create_pet(self, *, body: models.NewPet) -> models.Pet:
        pet = models.Pet(id=len(self.pets) + 1, name=body.name, tag=body.tag)
        self.pets[pet.id] = pet
        return pet

    def get_pet(self, *, pet_id: int) -> models.Pet | HTTPResult[models.Error]:
        if (pet := self.pets.get(pet_id)) is None:
            return HTTPResult(404, models.Error(message=f"Pet {pet_id} not found"))
        return pet
uv add uvicorn
uv run uvicorn app.server.main:app

Call it with the client in call.py, which sends to the document's server URL by default:

from app.client import Client
from app.client.errors import NotFoundError
from app.models import NewPet

with Client() as client:
    pet = client.pets.create_pet(body=NewPet(name="Mimi", tag="cat"))
    print(pet)
    for listed in client.pets.list_pets(limit=10).root:
        print(listed.name)
    try:
        client.pets.get_pet(pet_id=99)
    except NotFoundError as error:
        print(error.status_code, error.body)

It prints:

id=1 name='Mimi' tag='cat'
Mimi
404 message='Pet 99 not found'

AsyncClient offers the same methods as coroutines. See FastAPI Server Generation and Python Client Generation for every option, the pyproject.toml settings, authentication, and the Python API.


🍳 Common Recipes

CLI option quick starts

Use these starting points when combining options; each option links to the generated CLI reference for details and examples.

See the CLI Reference for the full option list and category-specific recipes.

πŸ€– Get CLI Help from LLMs

Generate a prompt to ask LLMs about CLI options:

datamodel-codegen --generate-prompt "Best options for Pydantic v2?" | claude -p

See LLM Integration for more examples.

🌐 Generate from URL

pip install 'datamodel-code-generator[http]'
datamodel-codegen --url https://example.com/api/openapi.yaml --output model.py

The http extra is the stable, non-deprecated backend. For the experimental HTTPX2 alternative, pass --http-backend httpx2; see HTTP backend selection.

βš™οΈ Use with pyproject.toml

pyproject.toml
[tool.datamodel-codegen]
input = "schema.yaml"
output = "src/models.py"
output-model-type = "pydantic_v2.BaseModel"

Then simply run:

datamodel-codegen

See pyproject.toml Configuration for more options.

πŸ”„ CI/CD Integration

Validate generated models in your CI pipeline:

.github/workflows/validate-models.yml
# Replace vX.Y.Z with a released action version.
- uses: datamodel-code-generator/datamodel-code-generator@vX.Y.Z
  with:
    input: schemas/api.yaml
    output: src/models/api.py

See CI/CD Integration for more options.


πŸ“š Next Steps


πŸ’– Sponsors

OpenAI Logo

OpenAI


🏒 Used by

These public examples are grouped by how each project uses datamodel-code-generator.

Code generation and runtime integration

Development, testing, and evaluation

See all dependents β†’


πŸ‘₯ Maintainers