Skip to content

📋 Generate from JSON Schema

Generate Pydantic models from JSON Schema definitions. See Supported Data Types for supported JSON Schema features.

🚀 Quick Start

datamodel-codegen \
    --input person.json \
    --input-file-type jsonschema \
    --output-model-type pydantic_v2.BaseModel \
    --output model.py

📝 Example

person.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Person",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "description": "The person's first name."
    },
    "lastName": {
      "type": "string",
      "description": "The person's last name."
    },
    "age": {
      "description": "Age in years which must be equal to or greater than zero.",
      "type": "integer",
      "minimum": 0
    },
    "friends": {
      "type": "array"
    },
    "comment": {
      "type": "null"
    }
  }
}

✨ Generated model.py

# generated by datamodel-codegen:
#   filename:  person.json
#   timestamp: 2020-04-27T16:12:27+00:00

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field, conint


class Person(BaseModel):
    firstName: str | None = Field(None, description="The person's first name.")
    lastName: str | None = Field(None, description="The person's last name.")
    age: conint(ge=0) | None = Field(
        None, description='Age in years which must be equal to or greater than zero.'
    )
    friends: list | None = None
    comment: Any | None = None

Tuple validation

JSON Schema's prefixItems syntax lets you describe heterogeneous arrays.

When:

  • prefixItems is present
  • no items are specified
  • minItems/maxItems match the number of prefix entries

datamodel-code-generator emits precise tuple annotations.

Example

{
  "$defs": {
    "Span": {
      "type": "object",
      "properties": {
        "value": { "type": "integer" }
      },
      "required": ["value"]
    }
  },
  "title": "defaults",
  "type": "object",
  "properties": {
    "a": {
      "type": "array",
      "prefixItems": [
        { "$ref": "#/$defs/Span" },
        { "type": "string" }
      ],
      "minItems": 2,
      "maxItems": 2
    }
  },
  "required": ["a"]
}
from pydantic import BaseModel


class Span(BaseModel):
    value: int


class Defaults(BaseModel):
    a: tuple[Span, str]

Custom Base Class with customBasePath

You can specify custom base classes directly in your JSON Schema using the customBasePath extension. This allows you to define base classes at the schema level without using CLI options.

Single Base Class

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "customBasePath": "myapp.models.UserBase",
  "properties": {
    "name": {"type": "string"},
    "email": {"type": "string"}
  },
  "required": ["name", "email"]
}

Generated Output:

from __future__ import annotations

from myapp.models import UserBase


class User(UserBase):
    name: str
    email: str

Multiple Base Classes (Mixins)

You can also specify multiple base classes as a list to implement mixin patterns:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "customBasePath": ["mixins.AuditMixin", "mixins.TimestampMixin"],
  "properties": {
    "name": {"type": "string"},
    "email": {"type": "string"}
  },
  "required": ["name", "email"]
}

Generated Output:

from __future__ import annotations

from mixins import AuditMixin, TimestampMixin


class User(AuditMixin, TimestampMixin):
    name: str
    email: str

Mixin Usage

When using multiple base classes, the specified classes are used directly without adding BaseModel. Ensure your mixins inherit from pydantic.BaseModel if you need Pydantic model behavior.

Priority Resolution

When multiple base class configurations are present, they are resolved in this order:

  1. --base-class-map (CLI option) - Highest priority
  2. customBasePath (JSON Schema extension)
  3. --base-class (CLI option) - Lowest priority (default for all models)

This allows you to set a default base class with --base-class, override specific models in the schema with customBasePath, and further override at the CLI level with --base-class-map.


📖 See Also