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 \
    --use-annotated \
    --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 Annotated, Any

from pydantic import BaseModel, Field


class Person(BaseModel):
    firstName: Annotated[str | None, Field(description="The person's first name.")] = None
    lastName: Annotated[str | None, Field(description="The person's last name.")] = None
    age: Annotated[
        int | None,
        Field(
            description='Age in years which must be equal to or greater than zero.',
            ge=0,
        ),
    ] = None
    friends: list[Any] | None = None
    comment: Annotated[None, Field(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.

Supported JSON Schema Features

Feature Generation behavior
Object properties and required fields Generated as model fields
$ref, $defs, and definitions Resolved before model generation
oneOf, anyOf, allOf Converted into unions and composed models where possible
Scalar constraints Generated as Field(...) metadata with --field-constraints / --use-annotated
format values Mapped to Python/Pydantic types where supported
Custom extensions customBasePath and related options can steer generated base classes

Limitations

JSON Schema input generates Python model definitions. It does not perform runtime validation by itself, and some schema keywords are represented as type hints or field metadata rather than full JSON Schema validator behavior. See Schema Version Support for version-specific coverage.


📖 See Also