Skip to content

🏷️ Field Customization

📋 Options

Option Description
--aliases Apply custom field and class name aliases via inline JSON or...
--capitalize-enum-members Capitalize enum member names to UPPER_CASE format.
--capitalize-numbered-enum-members Capitalize the numbered name an enum member takes when its n...
--default-values Override field default values via inline JSON or a JSON file...
--deserialize-default-values Deserialize selected direct scalar field defaults into their...
--empty-enum-field-name Name for empty string enum field values.
--extra-fields Configure how generated models handle extra fields not defin...
--field-constraints Generate Field() with validation constraints from schema.
--field-extra-keys Include specific extra keys in Field() definitions.
--field-extra-keys-without-x-prefix Include schema extension keys in Field() without requiring '...
--field-include-all-keys Include all schema keys in Field() json_schema_extra.
--field-type-collision-strategy Rename type class instead of field when names collide (Pydan...
--infer-union-variant-names Name inline oneOf/anyOf branch models after the value of the...
--merge-shared-variant-tags Give a variant that discriminated unions tag differently eve...
--name-allof-union-members-after-branches Name the classes an allOf gives the branches of a oneOf or a...
--no-alias Disable Field alias generation for non-Python-safe property ...
--no-deserialize-default-values Keep serialized schema defaults instead of deserializing sel...
--omit-redundant-constraints Do not write a constraint again beside a type that already e...
--original-field-name-delimiter Specify delimiter for original field names when using snake-...
--read-length-keywords-by-type Read the string and the array keywords for their own kind on...
--read-msgspec-union-bounds-exactly Decide the bounds of the int member of a msgspec union on th...
--remove-special-field-name-prefix Remove the special prefix from field names.
--serialization-aliases Apply custom Pydantic v2 serialization aliases via inline JS...
--set-default-enum-member Use the legacy flag for deserializing enum defaults.
--snake-case-field Convert field names to snake_case format.
--special-field-name-prefix Prefix to add to special field names (like reserved keywords...
--use-attribute-docstrings Generate field descriptions as attribute docstrings instead ...
--use-enum-values-in-discriminator Use enum values in discriminator mappings for union types.
--use-field-description Include schema descriptions as Field docstrings.
--use-field-description-example Add field examples to docstrings.
--use-inline-field-description Add field descriptions as inline comments.
--use-one-model-per-ref-site Give an object $ref with sibling keywords one model per pl...
--use-schema-description Use schema description as class docstring.
--use-serialization-alias Use serialization_alias instead of alias for field aliasing ...
--use-single-line-docstring Emit short docstrings on a single line.
--use-site-models-for-constrained-refs Give an allOf of $ref members whose other parts add assert...
--use-tag-as-union-variant-name Name inline oneOf/anyOf branch models after their tag: what ...
--use-title-as-name Use schema title as the generated class name.

🍳 Recipes

Normalize incoming field names

Convert source names to Python identifiers while preserving explicit alias data for runtime IO.

Options: --snake-case-field, --original-field-name-delimiter, --aliases

Carry schema documentation into models

Promote schema and field descriptions into generated docstrings or field metadata.

Options: --use-schema-description, --use-field-description, --use-field-description-example


--aliases

Apply custom field and class name aliases via inline JSON or a JSON file path.

The --aliases option allows renaming fields and classes via an inline JSON object or JSON mapping file, providing fine-grained control over generated names independent of schema definitions.

See also: Field Aliases

Usage

datamodel-codegen --input api.yaml --aliases openapi/aliases.json --target-python-version 3.10 # (1)!
  1. --aliases - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    x-amazon-apigateway-integration:
      uri:
        Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
      passthroughBehavior: when_no_templates
      httpMethod: POST
      type: aws_proxy
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          default: 1
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Users:
      type: array
      items:
        required:
          - id
          - name
        properties:
          id:
            type: integer
            format: int64
          name:
            type: string
          tag:
            type: string
    Id:
      type: string
    Rules:
      type: array
      items:
        type: string
    Error:
      description: error result
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    apis:
      type: array
      items:
        type: object
        properties:
          apiKey:
            type: string
            description: To be used as a dataset parameter value
          apiVersionNumber:
            type: string
            description: To be used as a version parameter value
          apiUrl:
            type: string
            format: uri
            description: "The URL describing the dataset's fields"
          apiDocumentationUrl:
            type: string
            format: uri
            description: A URL to the API console for each API
    Event:
      type: object
      description: Event object
      properties:
        name:
          type: string
    Result:
        type: object
        properties:
          event:
            $ref: '#/components/schemas/Event'

Output:

# generated by datamodel-codegen:
#   filename:  api.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Annotated, TypeAlias

from msgspec import UNSET, Meta, Struct, UnsetType, field


class Pet(Struct):
    id_: int = field(name='id')
    name_: str = field(name='name')
    tag: str | UnsetType = UNSET


Pets: TypeAlias = list[Pet]


class User(Struct):
    id_: int = field(name='id')
    name_: str = field(name='name')
    tag: str | UnsetType = UNSET


Users: TypeAlias = list[User]


Id: TypeAlias = str


Rules: TypeAlias = list[str]


class Error(Struct):
    code: int
    message: str


class Api(Struct):
    apiKey: (
        Annotated[str, Meta(description='To be used as a dataset parameter value')]
        | UnsetType
    ) = UNSET
    apiVersionNumber: (
        Annotated[str, Meta(description='To be used as a version parameter value')]
        | UnsetType
    ) = UNSET
    apiUrl: (
        Annotated[str, Meta(description="The URL describing the dataset's fields")]
        | UnsetType
    ) = UNSET
    apiDocumentationUrl: (
        Annotated[str, Meta(description='A URL to the API console for each API')]
        | UnsetType
    ) = UNSET


Apis: TypeAlias = list[Api]


class Event(Struct):
    name_: str | UnsetType = field(name='name', default=UNSET)


class Result(Struct):
    event: Event | UnsetType = UNSET

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Root",
  "properties": {
    "name": {
      "type": "string"
    },
    "user": {
      "type": "object",
      "title": "User",
      "properties": {
        "name": {
          "type": "string"
        },
        "id": {
          "type": "integer"
        }
      }
    },
    "address": {
      "type": "object",
      "title": "Address",
      "properties": {
        "name": {
          "type": "string"
        },
        "city": {
          "type": "string"
        }
      }
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  hierarchical_aliases.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class User(BaseModel):
    user_name: str | None = Field(None, alias='name')
    id: int | None = None


class Address(BaseModel):
    address_name: str | None = Field(None, alias='name')
    city: str | None = None


class Root(BaseModel):
    root_name: str | None = Field(None, alias='name')
    user: User | None = Field(None, title='User')
    address: Address | None = Field(None, title='Address')

Input Schema:

scalar DateTime

type DateTimePeriod {
    from: DateTime!
    to: DateTime!
}

Output:

# generated by datamodel-codegen:
#   filename:  field-aliases.graphql
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field
from typing_extensions import TypeAliasType

Boolean = TypeAliasType("Boolean", bool)
"""
The `Boolean` scalar type represents `true` or `false`.
"""


DateTime = TypeAliasType("DateTime", str)


String = TypeAliasType("String", str)
"""
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
"""


class DateTimePeriod(BaseModel):
    periodFrom: DateTime = Field(..., alias='from')
    periodTo: DateTime = Field(..., alias='to')
    typename__: Literal['DateTimePeriod'] | None = Field(
        'DateTimePeriod', alias='__typename'
    )

--capitalize-enum-members

Capitalize enum member names to UPPER_CASE format.

The --capitalize-enum-members flag converts enum member names to UPPER_CASE format (e.g., active becomes ACTIVE), following Python naming conventions for constants.

Aliases: --capitalise-enum-members | Related: --snake-case-field

Usage

datamodel-codegen --input many_case_enum.json --capitalize-enum-members # (1)!
  1. --capitalize-enum-members - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "string",
  "enum": [
    "snake_case",
    "CAP_CASE",
    "CamelCase",
    "UPPERCASE"
  ]
}

Output:

# generated by datamodel-codegen:
#   filename:  many_case_enum.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum


class Model(Enum):
    SNAKE_CASE = 'snake_case'
    CAP_CASE = 'CAP_CASE'
    CAMEL_CASE = 'CamelCase'
    UPPERCASE = 'UPPERCASE'

--capitalize-numbered-enum-members

Capitalize the numbered name an enum member takes when its name is taken.

Under --capitalize-enum-members the members a and A both capitalize to A, so the second one is numbered, and the number goes on the name as written: a_1. With --capitalize-numbered-enum-members the numbered name is capitalized too: A_1. Without --capitalize-enum-members the option changes nothing.

Aliases: --capitalise-numbered-enum-members | Related: --capitalize-enum-members

Usage

datamodel-codegen --input capitalise_numbered_enum_members.json --capitalize-enum-members --capitalize-numbered-enum-members # (1)!
  1. --capitalize-numbered-enum-members - the option documented here
Examples

Input Schema:

{
  "title": "Holder",
  "type": "object",
  "properties": {
    "kind": {"type": "string", "enum": ["a", "A", "a_1", "b"]},
    "mode": {"type": "string", "enum": ["On", "ON", "on"]}
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  capitalise_numbered_enum_members.json

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel


class Kind(Enum):
    A = 'a'
    A_1 = 'A'
    A_1_1 = 'a_1'
    B = 'b'


class Mode(Enum):
    ON = 'On'
    ON_1 = 'ON'
    ON_2 = 'on'


class Holder(BaseModel):
    kind: Kind | None = None
    mode: Mode | None = None
# generated by datamodel-codegen:
#   filename:  capitalise_numbered_enum_members.json

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel


class Kind(Enum):
    A = 'a'
    a_1 = 'A'
    A_1 = 'a_1'
    B = 'b'


class Mode(Enum):
    ON = 'On'
    on_1 = 'ON'
    on_2 = 'on'


class Holder(BaseModel):
    kind: Kind | None = None
    mode: Mode | None = None

--default-values

Override field default values via inline JSON or a JSON file path.

The --default-values option allows specifying default values for fields via an inline JSON object or JSON file. Supports scoped format (ClassName.field) for hierarchical overrides.

Usage

datamodel-codegen --input default_values_override.json --default-values default_values/scoped_defaults.json # (1)!
  1. --default-values - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "User": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "page": {
          "type": "integer"
        }
      },
      "required": ["name"]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  default_values_override.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, RootModel


class Model(RootModel[Any]):
    root: Any


class User(BaseModel):
    name: str
    status: str | None = 'active'
    page: int | None = 1

--deserialize-default-values

Deserialize selected direct scalar field defaults into their generated Python types.

The --deserialize-default-values option accepts an explicit list of generated value types. For example, --deserialize-default-values decimal emits a direct Decimal field's valid string default as a Decimal value, while --deserialize-default-values enum emits matching scalar and list defaults as enum members. Defaults that cannot be deserialized remain serialized so the generated module stays importable.

Usage

datamodel-codegen --input serialized_decimal_defaults.json --deserialize-default-values decimal --target-python-version 3.10 # (1)!
  1. --deserialize-default-values - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Invoice",
  "type": "object",
  "properties": {
    "amount": {
      "type": "string",
      "format": "decimal",
      "default": "12.340"
    },
    "invalid_amount": {
      "type": "string",
      "format": "decimal",
      "default": "not-a-decimal"
    },
    "nullable_amount": {
      "type": ["string", "null"],
      "format": "decimal",
      "default": null
    },
    "label": {
      "type": "string",
      "default": "retail"
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  serialized_decimal_defaults.json

from __future__ import annotations

from decimal import Decimal

from pydantic import BaseModel


class Invoice(BaseModel):
    amount: Decimal | None = Decimal('12.340')
    invalid_amount: Decimal | None = 'not-a-decimal'
    nullable_amount: Decimal | None = None
    label: str | None = 'retail'
# generated by datamodel-codegen:
#   filename:  serialized_decimal_defaults.json

from __future__ import annotations

from decimal import Decimal

from pydantic.dataclasses import dataclass


@dataclass
class Invoice:
    amount: Decimal | None = Decimal('12.340')
    invalid_amount: Decimal | None = 'not-a-decimal'
    nullable_amount: Decimal | None = None
    label: str | None = 'retail'
# generated by datamodel-codegen:
#   filename:  serialized_decimal_defaults.json

from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal


@dataclass
class Invoice:
    amount: Decimal | None = Decimal('12.340')
    invalid_amount: Decimal | None = 'not-a-decimal'
    nullable_amount: Decimal | None = None
    label: str | None = 'retail'
# generated by datamodel-codegen:
#   filename:  serialized_decimal_defaults.json

from __future__ import annotations

from decimal import Decimal
from typing import TypedDict

from typing_extensions import NotRequired


class Invoice(TypedDict):
    amount: NotRequired[Decimal]
    invalid_amount: NotRequired[Decimal]
    nullable_amount: NotRequired[Decimal | None]
    label: NotRequired[str]
# generated by datamodel-codegen:
#   filename:  serialized_decimal_defaults.json

from __future__ import annotations

from decimal import Decimal

from msgspec import UNSET, Struct, UnsetType


class Invoice(Struct):
    amount: Decimal | UnsetType = Decimal('12.340')
    invalid_amount: Decimal | UnsetType = 'not-a-decimal'
    nullable_amount: Decimal | None | UnsetType = UNSET
    label: str | UnsetType = 'retail'

--empty-enum-field-name

Name for empty string enum field values.

The --empty-enum-field-name flag configures the code generation behavior.

Usage

datamodel-codegen --input special_enum.json --empty-enum-field-name empty # (1)!
  1. --empty-enum-field-name - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "string",
  "enum": [
    true,
    false,
    "",
    "\n",
    "\r\n",
    "\t",
    "\\x08",
    null,
    "\\"
  ]
}

Output:

# generated by datamodel-codegen:
#   filename:  special_enum.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum

from pydantic import RootModel


class ModelEnum(Enum):
    True_ = True
    False_ = False
    empty = ''
    field_ = '\n'
    field__ = '\r\n'
    field__1 = '\t'
    field_x08 = '\\x08'
    field__2 = '\\'


class Model(RootModel[ModelEnum | None]):
    root: ModelEnum | None = None

--extra-fields

Configure how generated models handle extra fields not defined in schema.

The --extra-fields flag sets the generated models to allow, forbid, or ignore extra fields. With --extra-fields allow, models will accept and store fields not defined in the schema. Options: allow, ignore, forbid.

Usage

datamodel-codegen --input simple-star-wars.graphql --extra-fields allow # (1)!
  1. --extra-fields - the option documented here
Examples

Input Schema:

type Person {
    id: ID!
    name: String!
    height: Int
    mass: Int
    hair_color: String
    skin_color: String
    eye_color: String
    birth_year: String
    gender: String

    # Relationships
    homeworld_id: ID
    homeworld: Planet
    species: [Species!]!
    species_ids: [ID!]!
    films: [Film!]!
    films_ids: [ID!]!
    starships: [Starship!]!
    starships_ids: [ID!]!
    vehicles: [Vehicle!]!
    vehicles_ids: [ID!]!
}

type Planet {
    id: ID!
    name: String!
    rotation_period: String
    orbital_period: String
    diameter: String
    climate: String
    gravity: String
    terrain: String
    surface_water: String
    population: String

    # Relationships
    residents: [Person!]!
    residents_ids: [ID!]!
    films: [Film!]!
    films_ids: [ID!]!
}

type Species {
    id: ID!
    name: String!
    classification: String
    designation: String
    average_height: String
    skin_colors: String
    hair_colors: String
    eye_colors: String
    average_lifespan: String
    language: String

    # Relationships
    people: [Person!]!
    people_ids: [ID!]!
    films: [Film!]!
    films_ids: [ID!]!
}

type Vehicle {
    id: ID!
    name: String!
    model: String
    manufacturer: String
    cost_in_credits: String
    length: String
    max_atmosphering_speed: String
    crew: String
    passengers: String
    cargo_capacity: String
    consumables: String
    vehicle_class: String

    # Relationships
    pilots: [Person!]!
    pilots_ids: [ID!]!
    films: [Film!]!
    films_ids: [ID!]!
}

type Starship {
    id: ID!
    name: String!
    model: String
    manufacturer: String
    cost_in_credits: String
    length: String
    max_atmosphering_speed: String
    crew: String
    passengers: String
    cargo_capacity: String
    consumables: String
    hyperdrive_rating: String
    MGLT: String
    starship_class: String

    # Relationships
    pilots: [Person!]!
    pilots_ids: [ID!]!
    films: [Film!]!
    films_ids: [ID!]!
}

type Film {
  id: ID!
  title: String!
  episode_id: Int!
  opening_crawl: String!
  director: String!
  producer: String
  release_date: String!

  # Relationships
  characters: [Person!]!
  characters_ids: [ID!]!
  planets: [Planet!]!
  planets_ids: [ID!]!
  starships: [Starship!]!
  starships_ids: [ID!]!
  vehicles: [Vehicle!]!
  vehicles_ids: [ID!]!
  species: [Species!]!
  species_ids: [ID!]!
}

type Query {
  planet(id: ID!): Planet
  listPlanets(page: Int): [Planet!]!
  person(id: ID!): Person
  listPeople(page: Int): [Person!]!
  species(id: ID!): Species
  listSpecies(page: Int): [Species!]!
  film(id: ID!): Film
  listFilms(page: Int): [Film!]!
  starship(id: ID!): Starship
  listStarships(page: Int): [Starship!]!
  vehicle(id: ID!): Vehicle
  listVehicles(page: Int): [Vehicle!]!
}

Output:

# generated by datamodel-codegen:
#   filename:  simple-star-wars.graphql
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, ConfigDict, Field
from typing_extensions import TypeAliasType

Boolean = TypeAliasType("Boolean", bool)
"""
The `Boolean` scalar type represents `true` or `false`.
"""


ID = TypeAliasType("ID", str)
"""
The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
"""


Int = TypeAliasType("Int", int)
"""
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
"""


String = TypeAliasType("String", str)
"""
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
"""


class Film(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    characters: list[Person]
    characters_ids: list[ID]
    director: String
    episode_id: Int
    id: ID
    opening_crawl: String
    planets: list[Planet]
    planets_ids: list[ID]
    producer: String | None = None
    release_date: String
    species: list[Species]
    species_ids: list[ID]
    starships: list[Starship]
    starships_ids: list[ID]
    title: String
    vehicles: list[Vehicle]
    vehicles_ids: list[ID]
    typename__: Literal['Film'] | None = Field('Film', alias='__typename')


class Person(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    birth_year: String | None = None
    eye_color: String | None = None
    films: list[Film]
    films_ids: list[ID]
    gender: String | None = None
    hair_color: String | None = None
    height: Int | None = None
    homeworld: Planet | None = None
    homeworld_id: ID | None = None
    id: ID
    mass: Int | None = None
    name: String
    skin_color: String | None = None
    species: list[Species]
    species_ids: list[ID]
    starships: list[Starship]
    starships_ids: list[ID]
    vehicles: list[Vehicle]
    vehicles_ids: list[ID]
    typename__: Literal['Person'] | None = Field('Person', alias='__typename')


class Planet(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    climate: String | None = None
    diameter: String | None = None
    films: list[Film]
    films_ids: list[ID]
    gravity: String | None = None
    id: ID
    name: String
    orbital_period: String | None = None
    population: String | None = None
    residents: list[Person]
    residents_ids: list[ID]
    rotation_period: String | None = None
    surface_water: String | None = None
    terrain: String | None = None
    typename__: Literal['Planet'] | None = Field('Planet', alias='__typename')


class Species(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    average_height: String | None = None
    average_lifespan: String | None = None
    classification: String | None = None
    designation: String | None = None
    eye_colors: String | None = None
    films: list[Film]
    films_ids: list[ID]
    hair_colors: String | None = None
    id: ID
    language: String | None = None
    name: String
    people: list[Person]
    people_ids: list[ID]
    skin_colors: String | None = None
    typename__: Literal['Species'] | None = Field('Species', alias='__typename')


class Starship(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    MGLT: String | None = None
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    films: list[Film]
    films_ids: list[ID]
    hyperdrive_rating: String | None = None
    id: ID
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    name: String
    passengers: String | None = None
    pilots: list[Person]
    pilots_ids: list[ID]
    starship_class: String | None = None
    typename__: Literal['Starship'] | None = Field('Starship', alias='__typename')


class Vehicle(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    films: list[Film]
    films_ids: list[ID]
    id: ID
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    name: String
    passengers: String | None = None
    pilots: list[Person]
    pilots_ids: list[ID]
    vehicle_class: String | None = None
    typename__: Literal['Vehicle'] | None = Field('Vehicle', alias='__typename')


Film.model_rebuild()
Person.model_rebuild()

--field-constraints

Generate Field() with validation constraints from schema.

The --field-constraints flag generates Pydantic Field() definitions with validation constraints (min/max length, pattern, etc.) from the schema.

Related: --strict-types

See also: Field Constraints

Usage

datamodel-codegen --input api_constrained.yaml --field-constraints # (1)!
  1. --field-constraints - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 100
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    x-amazon-apigateway-integration:
      uri:
        Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
      passthroughBehavior: when_no_templates
      httpMethod: POST
      type: aws_proxy
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          minimum: 0
          maximum: 9223372036854775807
        name:
          type: string
          maxLength: 256
        tag:
          type: string
          maxLength: 64
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
      maxItems: 10
      minItems: 1
      uniqueItems: true
    UID:
      type: integer
      minimum: 0
    Users:
      type: array
      items:
        required:
          - id
          - name
          - uid
        properties:
          id:
            type: integer
            format: int64
            minimum: 0
          name:
            type: string
            maxLength: 256
          tag:
            type: string
            maxLength: 64
          uid:
            $ref: '#/components/schemas/UID'
          phones:
            type: array
            items:
              type: string
              minLength: 3
            maxItems: 10
          fax:
            type: array
            items:
              type: string
              minLength: 3
          height:
            type:
              - integer
              - number
            minimum: 1
            maximum: 300
          weight:
            type:
              - number
              - integer
            minimum: 1.0
            maximum: 1000.0
          age:
            type: integer
            minimum: 0.0
            maximum: 200.0
            exclusiveMinimum: true
          rating:
            type: number
            minimum: 0
            exclusiveMinimum: true
            maximum: 5

    Id:
      type: string
    Rules:
      type: array
      items:
        type: string
    Error:
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    apis:
      type: array
      items:
        type: object
        properties:
          apiKey:
            type: string
            description: To be used as a dataset parameter value
          apiVersionNumber:
            type: string
            description: To be used as a version parameter value
          apiUrl:
            type: string
            format: uri
            minLength: 1
            description: "The URL describing the dataset's fields"
          apiDocumentationUrl:
            type: string
            format: uri
            description: A URL to the API console for each API
    Event:
      type: object
      properties:
        name:
          type: string
    Result:
        type: object
        properties:
          event:
            $ref: '#/components/schemas/Event'

Output:

# generated by datamodel-codegen:
#   filename:  api_constrained.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import AnyUrl, BaseModel, Field, RootModel


class Pet(BaseModel):
    id: int = Field(..., ge=0, le=9223372036854775807)
    name: str = Field(..., max_length=256)
    tag: str | None = Field(None, max_length=64)


class Pets(RootModel[list[Pet]]):
    root: list[Pet] = Field(..., max_length=10, min_length=1)


class UID(RootModel[int]):
    root: int = Field(..., ge=0)


class Phone(RootModel[str]):
    root: str = Field(..., min_length=3)


class FaxItem(RootModel[str]):
    root: str = Field(..., min_length=3)


class User(BaseModel):
    id: int = Field(..., ge=0)
    name: str = Field(..., max_length=256)
    tag: str | None = Field(None, max_length=64)
    uid: UID
    phones: list[Phone] | None = Field(None, max_length=10)
    fax: list[FaxItem] | None = None
    height: int | float | None = Field(None, ge=1.0, le=300.0)
    weight: float | int | None = Field(None, ge=1.0, le=1000.0)
    age: int | None = Field(None, gt=0, le=200)
    rating: float | None = Field(None, gt=0.0, le=5.0)


class Users(RootModel[list[User]]):
    root: list[User]


class Id(RootModel[str]):
    root: str


class Rules(RootModel[list[str]]):
    root: list[str]


class Error(BaseModel):
    code: int
    message: str


class Api(BaseModel):
    apiKey: str | None = Field(
        None, description='To be used as a dataset parameter value'
    )
    apiVersionNumber: str | None = Field(
        None, description='To be used as a version parameter value'
    )
    apiUrl: AnyUrl | None = Field(
        None, description="The URL describing the dataset's fields"
    )
    apiDocumentationUrl: AnyUrl | None = Field(
        None, description='A URL to the API console for each API'
    )


class Apis(RootModel[list[Api]]):
    root: list[Api]


class Event(BaseModel):
    name: str | None = None


class Result(BaseModel):
    event: Event | None = None

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "properties": {
        "name": {
          "type": "string",
          "example": "ken"
        },
        "age": {
          "type": "integer"
        },
        "salary": {
          "type": "integer",
          "minimum": 0
        },
        "debt" : {
          "type": "integer",
          "maximum": 0
        },
        "loan" : {
          "type": "number",
          "maximum": 0
        },
        "tel": {
          "type": "string",
          "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$"
        },
        "height": {
          "type": "number",
          "minimum": 0
        },
        "weight": {
          "type": "number",
          "minimum": 0
        },
        "score": {
          "type": "number",
          "minimum": 1e-08
        },
        "active": {
          "type": "boolean"
        },
        "photo": {
          "type": "string",
          "format": "binary",
          "minLength": 100
        }
      }
}

Output:

# generated by datamodel-codegen:
#   filename:  strict_types.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import (
    BaseModel,
    Field,
    StrictBool,
    StrictBytes,
    StrictFloat,
    StrictInt,
    StrictStr,
)


class User(BaseModel):
    name: StrictStr | None = Field(None, examples=['ken'])
    age: StrictInt | None = None
    salary: StrictInt | None = Field(None, ge=0)
    debt: StrictInt | None = Field(None, le=0)
    loan: StrictFloat | None = Field(None, le=0.0)
    tel: StrictStr | None = Field(None, pattern='^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$')
    height: StrictFloat | None = Field(None, ge=0.0)
    weight: StrictFloat | None = Field(None, ge=0.0)
    score: StrictFloat | None = Field(None, ge=1e-08)
    active: StrictBool | None = None
    photo: StrictBytes | None = Field(None, min_length=100)

--field-extra-keys

Include specific extra keys in Field() definitions.

The --field-extra-keys flag configures the code generation behavior.

Usage

datamodel-codegen --input extras.json --field-extra-keys key2 --field-extra-keys-without-x-prefix x-repr # (1)!
  1. --field-extra-keys - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Extras",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "normal key",
      "key1": 123,
      "key2": 456,
      "$exclude": 123,
      "invalid-key-1": "abc",
      "-invalid+key_2": "efg",
      "$comment": "comment",
      "$id": "#name",
      "register": "hij",
      "schema": "klm",
      "x-repr": true,
      "x-abc": true,
      "example": "example",
      "readOnly": true
    },
    "age": {
      "type": "integer",
      "example": 12,
      "writeOnly": true,
      "examples": [
        13,
        20
      ]
    },
    "status": {
      "type": "string",
      "examples": [
        "active"
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  extras.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class Extras(BaseModel):
    name: str | None = Field(
        None,
        description='normal key',
        examples=['example'],
        json_schema_extra={'key2': 456, 'invalid-key-1': 'abc'},
        repr=True,
    )
    age: int | None = Field(None, examples=[13, 20], json_schema_extra={'example': 12})
    status: str | None = Field(None, examples=['active'])

--field-extra-keys-without-x-prefix

Include schema extension keys in Field() without requiring 'x-' prefix.

The --field-extra-keys-without-x-prefix option allows you to specify custom schema extension keys that should be included in Pydantic Field() extras without the 'x-' prefix requirement. For example, 'x-repr' in the schema becomes 'repr' in Field(). This is useful for custom schema extensions and vendor-specific metadata.

Usage

datamodel-codegen --input extras.json --field-include-all-keys --field-extra-keys-without-x-prefix x-repr # (1)!
  1. --field-extra-keys-without-x-prefix - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Extras",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "normal key",
      "key1": 123,
      "key2": 456,
      "$exclude": 123,
      "invalid-key-1": "abc",
      "-invalid+key_2": "efg",
      "$comment": "comment",
      "$id": "#name",
      "register": "hij",
      "schema": "klm",
      "x-repr": true,
      "x-abc": true,
      "example": "example",
      "readOnly": true
    },
    "age": {
      "type": "integer",
      "example": 12,
      "writeOnly": true,
      "examples": [
        13,
        20
      ]
    },
    "status": {
      "type": "string",
      "examples": [
        "active"
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  extras.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class Extras(BaseModel):
    name: str | None = Field(
        None,
        description='normal key',
        examples=['example'],
        json_schema_extra={
            'key1': 123,
            'key2': 456,
            '$exclude': 123,
            'invalid-key-1': 'abc',
            '-invalid+key_2': 'efg',
            '$comment': 'comment',
            'register': 'hij',
            'schema': 'klm',
            'x-abc': True,
            'readOnly': True,
        },
        repr=True,
    )
    age: int | None = Field(
        None, examples=[13, 20], json_schema_extra={'example': 12, 'writeOnly': True}
    )
    status: str | None = Field(None, examples=['active'])

--field-include-all-keys

Include all schema keys in Field() json_schema_extra.

The --field-include-all-keys flag configures the code generation behavior.

Usage

datamodel-codegen --input person.json --field-include-all-keys # (1)!
  1. --field-include-all-keys - the option documented here
Examples

Input Schema:

{
  "$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", "null"],
      "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"
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  person.json
#   timestamp: 2019-07-26T00:00:00+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[Any] | None = None
    comment: None = Field(None)

--field-type-collision-strategy

Rename type class instead of field when names collide (Pydantic v2 only).

The --field-type-collision-strategy flag controls how field name and type name collisions are resolved. With rename-type, the type class is renamed with a suffix to preserve the original field name, instead of renaming the field and adding an alias.

Usage

datamodel-codegen --input field_has_same_name.json --output-model-type pydantic_v2.BaseModel --field-type-collision-strategy rename-type # (1)!
  1. --field-type-collision-strategy - the option documented here
Examples

Input Schema:

{
  "title": "Test",
  "type": "object",
  "properties": {
    "TestObject": {
      "title": "TestObject",
      "type": "object",
      "properties": {
        "test_string": {
          "type": "string"
        }
      }
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  field_has_same_name.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class TestObject_1(BaseModel):
    test_string: str | None = None


class Test(BaseModel):
    TestObject: TestObject_1 | None = Field(None, title='TestObject')

--infer-union-variant-names

Name inline oneOf/anyOf branch models after the value of their tag field (Pet + type: "cat" -> PetCat) instead of Pet1, Pet2.

The --infer-union-variant-names flag uses branch-local const values or single-value enums on a shared discriminator-style property to name generated inline union models. This is useful when inline union branches would otherwise receive position-based names such as Event and Event1.

The literal value can also come from a single-value enum or an internal $ref. At least two branches need distinct values on the field; to also name a union's only tagged branch and branches tagged by their only key, use --use-tag-as-union-variant-name. Existing generated output is preserved unless this option is enabled.

Related: --use-tag-as-union-variant-name, --use-title-as-name

Usage

datamodel-codegen --input infer_union_variant_names.json --infer-union-variant-names # (1)!
  1. --infer-union-variant-names - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "WebhookEnvelope",
  "type": "object",
  "required": ["event"],
  "properties": {
    "event": {
      "oneOf": [
        {
          "type": "object",
          "required": ["type", "id"],
          "properties": {
            "type": {"const": "message.created"},
            "id": {"type": "string"}
          }
        },
        {
          "type": "object",
          "required": ["type", "reason"],
          "properties": {
            "type": {"const": "message.failed"},
            "reason": {"type": "string"}
          }
        }
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  infer_union_variant_names.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel


class EventMessageCreated(BaseModel):
    type: Literal['message.created']
    id: str


class EventMessageFailed(BaseModel):
    type: Literal['message.failed']
    reason: str


class WebhookEnvelope(BaseModel):
    event: EventMessageCreated | EventMessageFailed
# generated by datamodel-codegen:
#   filename:  infer_union_variant_names.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel


class Event(BaseModel):
    type: Literal['message.created']
    id: str


class Event1(BaseModel):
    type: Literal['message.failed']
    reason: str


class WebhookEnvelope(BaseModel):
    event: Event | Event1

--merge-shared-variant-tags

Give a variant that discriminated unions tag differently every tag they give it.

A variant that several discriminated unions list has one tag field. Without the option it keeps the tags of the first union that tags it, so a union that tags it otherwise, by a mapping key or by the schema name, rejects the documents that select the variant by a tag it does not keep, and a warning says so. With --merge-shared-variant-tags its tag field is a Literal of every tag the unions give it, so each union decodes the documents it selects the variant by; a union then also accepts the tags the other unions give the variant. A tag that the pattern of the tag field rejects is left out, as the schema rejects the documents it selects the variant by. A variant keeps the first union's tags where a union listing it, or nesting a union that lists it, would then read one of its tags on another variant, as crossing mappings do, and msgspec Structs, which take one tag, are unchanged.

Usage

datamodel-codegen --input discriminator_merged_variant_tags.yaml --merge-shared-variant-tags # (1)!
  1. --merge-shared-variant-tags - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info:
  title: Variants Shared by Discriminated Unions
  version: 1.0.0
paths: {}
components:
  schemas:
    Holder:
      type: object
      properties:
        byName:
          $ref: '#/components/schemas/ByName'
        byKey:
          $ref: '#/components/schemas/ByKey'
        stock:
          $ref: '#/components/schemas/Stock'
        herd:
          $ref: '#/components/schemas/Herd'
        pet:
          $ref: '#/components/schemas/Pet'
        animal:
          $ref: '#/components/schemas/Animal'
        forward:
          $ref: '#/components/schemas/Forward'
        backward:
          $ref: '#/components/schemas/Backward'
        mixed:
          $ref: '#/components/schemas/Mixed'
    Cat:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        meow: {type: string}
    Dog:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        bark: {type: string}
    ByName:
      oneOf:
        - $ref: '#/components/schemas/Cat'
        - $ref: '#/components/schemas/Dog'
      discriminator:
        propertyName: kind
    ByKey:
      oneOf:
        - $ref: '#/components/schemas/Cat'
        - $ref: '#/components/schemas/Dog'
      discriminator:
        propertyName: kind
        mapping:
          cat: '#/components/schemas/Cat'
          dog: '#/components/schemas/Dog'
    Cow:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        moo: {type: string}
    Pig:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        oink: {type: string}
    Stock:
      oneOf:
        - $ref: '#/components/schemas/Cow'
        - $ref: '#/components/schemas/Pig'
      discriminator:
        propertyName: kind
        mapping:
          cow: '#/components/schemas/Cow'
          pig: '#/components/schemas/Pig'
    Herd:
      oneOf:
        - $ref: '#/components/schemas/Cow'
        - $ref: '#/components/schemas/Pig'
      discriminator:
        propertyName: kind
    Fox:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        den: {type: string}
    Owl:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        nest: {type: string}
    Pet:
      oneOf:
        - $ref: '#/components/schemas/Fox'
        - $ref: '#/components/schemas/Owl'
      discriminator:
        propertyName: kind
        mapping:
          fox: '#/components/schemas/Fox'
          owl: '#/components/schemas/Owl'
    Animal:
      oneOf:
        - $ref: '#/components/schemas/Fox'
        - $ref: '#/components/schemas/Owl'
      discriminator:
        propertyName: kind
        mapping:
          vulpine: '#/components/schemas/Fox'
          avian: '#/components/schemas/Owl'
    Red:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        hue: {type: integer}
    Blue:
      type: object
      required: [kind]
      properties:
        kind: {type: string}
        depth: {type: integer}
    Forward:
      oneOf:
        - $ref: '#/components/schemas/Red'
        - $ref: '#/components/schemas/Blue'
      discriminator:
        propertyName: kind
        mapping:
          a: '#/components/schemas/Red'
          b: '#/components/schemas/Blue'
    Backward:
      oneOf:
        - $ref: '#/components/schemas/Red'
        - $ref: '#/components/schemas/Blue'
      discriminator:
        propertyName: kind
        mapping:
          b: '#/components/schemas/Red'
          a: '#/components/schemas/Blue'
    Name:
      type: string
    Mixed:
      oneOf:
        - $ref: '#/components/schemas/Cat'
        - $ref: '#/components/schemas/Name'
      discriminator:
        propertyName: kind

Output:

# generated by datamodel-codegen:
#   filename:  discriminator_merged_variant_tags.yaml

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field, RootModel


class Cat(BaseModel):
    kind: Literal['Cat', 'cat']
    meow: str | None = None


class Dog(BaseModel):
    kind: Literal['Dog', 'dog']
    bark: str | None = None


class ByName(RootModel[Cat | Dog]):
    root: Cat | Dog = Field(..., discriminator='kind')


class ByKey(RootModel[Cat | Dog]):
    root: Cat | Dog = Field(..., discriminator='kind')


class Cow(BaseModel):
    kind: Literal['cow', 'Cow']
    moo: str | None = None


class Pig(BaseModel):
    kind: Literal['pig', 'Pig']
    oink: str | None = None


class Stock(RootModel[Cow | Pig]):
    root: Cow | Pig = Field(..., discriminator='kind')


class Herd(RootModel[Cow | Pig]):
    root: Cow | Pig = Field(..., discriminator='kind')


class Fox(BaseModel):
    kind: Literal['fox', 'vulpine']
    den: str | None = None


class Owl(BaseModel):
    kind: Literal['owl', 'avian']
    nest: str | None = None


class Pet(RootModel[Fox | Owl]):
    root: Fox | Owl = Field(..., discriminator='kind')


class Animal(RootModel[Fox | Owl]):
    root: Fox | Owl = Field(..., discriminator='kind')


class Red(BaseModel):
    kind: Literal['a']
    hue: int | None = None


class Blue(BaseModel):
    kind: Literal['b']
    depth: int | None = None


class Forward(RootModel[Red | Blue]):
    root: Red | Blue = Field(..., discriminator='kind')


class Backward(RootModel[Red | Blue]):
    root: Red | Blue = Field(..., discriminator='kind')


class Name(RootModel[str]):
    root: str


class Mixed(RootModel[Cat | Name]):
    root: Cat | Name


class Holder(BaseModel):
    byName: ByName | None = None
    byKey: ByKey | None = None
    stock: Stock | None = None
    herd: Herd | None = None
    pet: Pet | None = None
    animal: Animal | None = None
    forward: Forward | None = None
    backward: Backward | None = None
    mixed: Mixed | None = None
# generated by datamodel-codegen:
#   filename:  discriminator_merged_variant_tags.yaml

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field, RootModel


class Cat(BaseModel):
    kind: Literal['Cat']
    meow: str | None = None


class Dog(BaseModel):
    kind: Literal['Dog']
    bark: str | None = None


class ByName(RootModel[Cat | Dog]):
    root: Cat | Dog = Field(..., discriminator='kind')


class ByKey(RootModel[Cat | Dog]):
    root: Cat | Dog = Field(..., discriminator='kind')


class Cow(BaseModel):
    kind: Literal['cow']
    moo: str | None = None


class Pig(BaseModel):
    kind: Literal['pig']
    oink: str | None = None


class Stock(RootModel[Cow | Pig]):
    root: Cow | Pig = Field(..., discriminator='kind')


class Herd(RootModel[Cow | Pig]):
    root: Cow | Pig = Field(..., discriminator='kind')


class Fox(BaseModel):
    kind: Literal['fox']
    den: str | None = None


class Owl(BaseModel):
    kind: Literal['owl']
    nest: str | None = None


class Pet(RootModel[Fox | Owl]):
    root: Fox | Owl = Field(..., discriminator='kind')


class Animal(RootModel[Fox | Owl]):
    root: Fox | Owl = Field(..., discriminator='kind')


class Red(BaseModel):
    kind: Literal['a']
    hue: int | None = None


class Blue(BaseModel):
    kind: Literal['b']
    depth: int | None = None


class Forward(RootModel[Red | Blue]):
    root: Red | Blue = Field(..., discriminator='kind')


class Backward(RootModel[Red | Blue]):
    root: Red | Blue = Field(..., discriminator='kind')


class Name(RootModel[str]):
    root: str


class Mixed(RootModel[Cat | Name]):
    root: Cat | Name


class Holder(BaseModel):
    byName: ByName | None = None
    byKey: ByKey | None = None
    stock: Stock | None = None
    herd: Herd | None = None
    pet: Pet | None = None
    animal: Animal | None = None
    forward: Forward | None = None
    backward: Backward | None = None
    mixed: Mixed | None = None

--name-allof-union-members-after-branches

Name the classes an allOf gives the branches of a oneOf or anyOf it holds after the branches.

An allOf that holds a oneOf or anyOf gives each branch a class that combines it with the other parts of the allOf. These classes are numbered after the holder, Event1 to Event5 for two branches, and --infer-union-variant-names names the branch-only bases after their tags, not the classes of the union. With --name-allof-union-members-after-branches each class of the union takes the holder's name and the branch's tag (under --infer-union-variant-names or --use-tag-as-union-variant-name), the class of a $ref branch, or its position (EventCreated, NoticeOpened, Event1), a branch-only base takes the class's name and Base (EventCreatedBase), and the part the branches share takes the holder's name and Base (EventBase).

Related: --infer-union-variant-names, --naming-strategy, --use-tag-as-union-variant-name

Usage

datamodel-codegen --input allof_union_members.yaml --name-allof-union-members-after-branches --infer-union-variant-names # (1)!
  1. --name-allof-union-members-after-branches - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info: {title: allOf union members, version: "1"}
paths: {}
components:
  schemas:
    Envelope:
      type: object
      required: [id]
      properties:
        id: {type: string}
    Event:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - oneOf:
            - type: object
              required: [type]
              properties:
                type: {type: string, enum: [created]}
                name: {type: string}
            - type: object
              required: [type]
              properties:
                type: {type: string, enum: [deleted]}
                reason: {type: string}
    Opened:
      type: object
      required: [state]
      properties:
        state: {type: string, enum: [opened]}
    Closed:
      type: object
      required: [state]
      properties:
        state: {type: string, enum: [closed]}
    Notice:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - oneOf:
            - $ref: '#/components/schemas/Opened'
            - $ref: '#/components/schemas/Closed'

Output:

# generated by datamodel-codegen:
#   filename:  allof_union_members.yaml

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, RootModel


class Envelope(BaseModel):
    id: str


class Type(Enum):
    created = 'created'


class EventCreatedBase(BaseModel):
    type: Type
    name: str | None = None


class Type1(Enum):
    deleted = 'deleted'


class EventDeletedBase(BaseModel):
    type: Type1
    reason: str | None = None


class EventBase(Envelope):
    pass


class EventCreated(EventCreatedBase, EventBase):
    pass


class EventDeleted(EventDeletedBase, EventBase):
    pass


class Event(RootModel[EventCreated | EventDeleted]):
    root: EventCreated | EventDeleted


class State(Enum):
    opened = 'opened'


class Opened(BaseModel):
    state: State


class State1(Enum):
    closed = 'closed'


class Closed(BaseModel):
    state: State1


class NoticeBase(Envelope):
    pass


class NoticeOpened(Opened, NoticeBase):
    pass


class NoticeClosed(Closed, NoticeBase):
    pass


class Notice(RootModel[NoticeOpened | NoticeClosed]):
    root: NoticeOpened | NoticeClosed
# generated by datamodel-codegen:
#   filename:  allof_union_members.yaml

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, RootModel


class Envelope(BaseModel):
    id: str


class Type(Enum):
    created = 'created'


class EventCreated(BaseModel):
    type: Type
    name: str | None = None


class Type1(Enum):
    deleted = 'deleted'


class EventDeleted(BaseModel):
    type: Type1
    reason: str | None = None


class Event1(Envelope):
    pass


class Event2(EventCreated, Event1):
    pass


class Event3(EventDeleted, Event1):
    pass


class Event(RootModel[Event2 | Event3]):
    root: Event2 | Event3


class State(Enum):
    opened = 'opened'


class Opened(BaseModel):
    state: State


class State1(Enum):
    closed = 'closed'


class Closed(BaseModel):
    state: State1


class Notice1(Envelope):
    pass


class Notice2(Opened, Notice1):
    pass


class Notice3(Closed, Notice1):
    pass


class Notice(RootModel[Notice2 | Notice3]):
    root: Notice2 | Notice3

--no-alias

Disable Field alias generation for non-Python-safe property names.

The --no-alias flag disables automatic alias generation when JSON property names contain characters invalid in Python (like hyphens). Without this flag, fields are renamed to Python-safe names with Field(alias='original-name'). With this flag, only Python-safe names are used without aliases.

See also: Field Aliases

Usage

datamodel-codegen --input no_alias.json --no-alias # (1)!
  1. --no-alias - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Person",
  "type": "object",
  "properties": {
    "first-name": {
      "type": "string"
    },
    "last-name": {
      "type": "string"
    },
    "email_address": {
      "type": "string"
    }
  },
  "required": ["first-name", "last-name"]
}

Output:

# generated by datamodel-codegen:
#   filename:  no_alias.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel


class Person(BaseModel):
    first_name: str
    last_name: str
    email_address: str | None = None
# generated by datamodel-codegen:
#   filename:  no_alias.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class Person(BaseModel):
    first_name: str = Field(..., alias='first-name')
    last_name: str = Field(..., alias='last-name')
    email_address: str | None = None

--no-deserialize-default-values

Keep serialized schema defaults instead of deserializing selected types.

The --no-deserialize-default-values flag explicitly disables default-value deserialization, including when a preset enables it. Compatibility warnings still identify direct scalar defaults whose serialized form does not match the generated Python type.

Related: --deserialize-default-values, --preset

Usage

datamodel-codegen --input serialized_decimal_defaults.json --preset standard-py310-20260826 --no-deserialize-default-values --disable-timestamp --formatters builtin # (1)!
  1. --no-deserialize-default-values - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Invoice",
  "type": "object",
  "properties": {
    "amount": {
      "type": "string",
      "format": "decimal",
      "default": "12.340"
    },
    "invalid_amount": {
      "type": "string",
      "format": "decimal",
      "default": "not-a-decimal"
    },
    "nullable_amount": {
      "type": ["string", "null"],
      "format": "decimal",
      "default": null
    },
    "label": {
      "type": "string",
      "default": "retail"
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  serialized_decimal_defaults.json

from __future__ import annotations

from decimal import Decimal

from pydantic import BaseModel, ConfigDict


class Invoice(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    amount: Decimal = '12.340'
    invalid_amount: Decimal = 'not-a-decimal'
    nullable_amount: Decimal | None = None
    label: str = 'retail'

--omit-redundant-constraints

Do not write a constraint again beside a type that already enforces it.

In the field forms (--field-constraints, --use-annotated), a zero-bound class from --use-non-positive-negative-number-constrained-types, such as NonNegativeInt, enforces its bound, so a nullable field, a root model or an item writes NonNegativeInt | None instead of repeating Field(ge=0); under --strict-types the field writes the bound beside StrictInt instead of a strict conint. The Literal of a const or an enum enforces the length and number constraints beside it by its values: values that violate them are left out and the field writes none of them, and a const branch of a oneOf or anyOf whose constraints its value meets stays a Literal instead of a root model. A pattern and a multipleOf the check cannot decide stay written.

Usage

datamodel-codegen --input redundant_constraints.json --use-annotated --use-non-positive-negative-number-constrained-types --use-single-value-enum-as-const --omit-redundant-constraints # (1)!
  1. --omit-redundant-constraints - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "RedundantConstraints",
  "type": "object",
  "$defs": {
    "Count": {"type": "integer", "minimum": 0},
    "NullableCount": {"type": ["integer", "null"], "minimum": 0},
    "Bounded": {"type": "integer", "minimum": 0, "maximum": 9},
    "Ratio": {"type": "number", "exclusiveMinimum": 0},
    "ModelIds": {"anyOf": [{"type": "string", "minLength": 1}, {"type": "string", "enum": ["gpt-live-1"]}]},
    "ConstIds": {"anyOf": [{"type": "string", "minLength": 1}, {"type": "string", "const": "gpt-live-1"}]},
    "Code": {"type": "string", "const": "abc", "minLength": 1},
    "Level": {"type": "string", "enum": ["a", "bb", "ccc"], "minLength": 2}
  },
  "properties": {
    "count": {"type": ["integer", "null"], "minimum": 0},
    "plain": {"type": "integer", "minimum": 0},
    "negative": {"type": ["integer", "null"], "exclusiveMaximum": 0},
    "positive": {"type": ["number", "null"], "exclusiveMinimum": 0},
    "both": {"type": ["integer", "null"], "minimum": 0, "maximum": 10},
    "counts": {"type": "array", "items": {"type": ["integer", "null"], "minimum": 0}},
    "root_count": {"$ref": "#/$defs/Count"},
    "nullable_count": {"$ref": "#/$defs/NullableCount"},
    "bounded": {"$ref": "#/$defs/Bounded"},
    "ratio": {"$ref": "#/$defs/Ratio"},
    "model": {"$ref": "#/$defs/ModelIds", "minLength": 1},
    "const_model": {"$ref": "#/$defs/ConstIds", "minLength": 1},
    "direct": {"type": "string", "const": "abc", "minLength": 1},
    "number": {"type": "integer", "const": 5, "minimum": 1},
    "codes": {"type": "array", "items": {"type": "string", "const": "abc", "minLength": 2}},
    "code": {"$ref": "#/$defs/Code"},
    "level": {"$ref": "#/$defs/Level"},
    "unmet": {"type": "string", "const": "abc", "maxLength": 2},
    "ratios": {"type": "array", "items": {"type": "number", "const": 1.5, "minimum": 1}},
    "patterned": {"type": "array", "items": {"type": "string", "const": "abc", "pattern": "^a", "minLength": 1}}
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  redundant_constraints.json

from __future__ import annotations

from enum import Enum
from typing import Annotated, Literal

from pydantic import (
    BaseModel,
    Field,
    NegativeInt,
    NonNegativeInt,
    PositiveFloat,
    RootModel,
)


class Count(RootModel[NonNegativeInt | None]):
    root: NonNegativeInt | None


class Model(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class ConstModel(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class Ratio1(RootModel[float]):
    root: Annotated[float, Field(ge=1.0)]


class CountModel(RootModel[NonNegativeInt]):
    root: NonNegativeInt


class NullableCount(RootModel[NonNegativeInt | None]):
    root: NonNegativeInt | None


class Bounded(RootModel[NonNegativeInt]):
    root: Annotated[NonNegativeInt, Field(le=9)]


class Ratio(RootModel[PositiveFloat]):
    root: PositiveFloat


class ModelIds1(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class ModelIds(RootModel[ModelIds1 | Literal['gpt-live-1']]):
    root: ModelIds1 | Literal['gpt-live-1']


class ConstIds1(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class ConstIds(RootModel[ConstIds1 | Literal['gpt-live-1']]):
    root: ConstIds1 | Literal['gpt-live-1']


class Code(RootModel[Literal['abc']]):
    root: Literal['abc']


class Level(Enum):
    bb = 'bb'
    ccc = 'ccc'


class RedundantConstraints(BaseModel):
    count: NonNegativeInt | None = None
    plain: NonNegativeInt | None = None
    negative: NegativeInt | None = None
    positive: PositiveFloat | None = None
    both: Annotated[NonNegativeInt | None, Field(le=10)] = None
    counts: list[Count | None] | None = None
    root_count: CountModel | None = None
    nullable_count: NullableCount | None = None
    bounded: Bounded | None = None
    ratio: Ratio | None = None
    model: Model | Literal['gpt-live-1'] | None = None
    const_model: ConstModel | Literal['gpt-live-1'] | None = None
    direct: Literal['abc'] | None = None
    number: Literal[5] | None = None
    codes: list[Literal['abc']] | None = None
    code: Code | None = None
    level: Level | None = None
    unmet: Annotated[Literal['abc'] | None, Field(max_length=2)] = None
    ratios: list[Ratio1] | None = None
    patterned: list[Literal['abc']] | None = None
# generated by datamodel-codegen:
#   filename:  redundant_constraints.json

from __future__ import annotations

from enum import Enum
from typing import Annotated, Literal

from pydantic import (
    BaseModel,
    Field,
    NegativeInt,
    NonNegativeInt,
    PositiveFloat,
    RootModel,
)


class Count(RootModel[NonNegativeInt | None]):
    root: Annotated[NonNegativeInt | None, Field(ge=0)]


class Model(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class Model1(RootModel[Literal['gpt-live-1']]):
    root: Annotated[Literal['gpt-live-1'], Field(min_length=1)]


class ConstModel(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class ConstModel1(RootModel[Literal['gpt-live-1']]):
    root: Annotated[Literal['gpt-live-1'], Field(min_length=1)]


class Code(RootModel[Literal['abc']]):
    root: Annotated[Literal['abc'], Field(min_length=2)]


class Ratio1(RootModel[float]):
    root: Annotated[float, Field(ge=1.0)]


class PatternedItem(RootModel[Literal['abc']]):
    root: Annotated[Literal['abc'], Field(min_length=1, pattern='^a')]


class CountModel(RootModel[NonNegativeInt]):
    root: Annotated[NonNegativeInt, Field(ge=0)]


class NullableCount(RootModel[NonNegativeInt | None]):
    root: Annotated[NonNegativeInt | None, Field(ge=0)]


class Bounded(RootModel[NonNegativeInt]):
    root: Annotated[NonNegativeInt, Field(ge=0, le=9)]


class Ratio(RootModel[PositiveFloat]):
    root: Annotated[PositiveFloat, Field(gt=0)]


class ModelIds1(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class ModelIds(RootModel[ModelIds1 | Literal['gpt-live-1']]):
    root: ModelIds1 | Literal['gpt-live-1']


class ConstIds1(RootModel[str]):
    root: Annotated[str, Field(min_length=1)]


class ConstIds(RootModel[ConstIds1 | Literal['gpt-live-1']]):
    root: ConstIds1 | Literal['gpt-live-1']


class CodeModel(RootModel[Literal['abc']]):
    root: Annotated[Literal['abc'], Field(min_length=1)]


class Level(Enum):
    bb = 'bb'
    ccc = 'ccc'


class RedundantConstraints(BaseModel):
    count: Annotated[NonNegativeInt | None, Field(ge=0)] = None
    plain: NonNegativeInt | None = None
    negative: Annotated[NegativeInt | None, Field(lt=0)] = None
    positive: Annotated[PositiveFloat | None, Field(gt=0)] = None
    both: Annotated[NonNegativeInt | None, Field(ge=0, le=10)] = None
    counts: list[Count | None] | None = None
    root_count: CountModel | None = None
    nullable_count: NullableCount | None = None
    bounded: Bounded | None = None
    ratio: Ratio | None = None
    model: Model | Model1 | None = None
    const_model: ConstModel | ConstModel1 | None = None
    direct: Annotated[Literal['abc'] | None, Field(min_length=1)] = None
    number: Annotated[Literal[5] | None, Field(ge=1)] = None
    codes: list[Code] | None = None
    code: CodeModel | None = None
    level: Level | None = None
    unmet: Annotated[Literal['abc'] | None, Field(max_length=2)] = None
    ratios: list[Ratio1] | None = None
    patterned: list[PatternedItem] | None = None

--original-field-name-delimiter

Specify delimiter for original field names when using snake-case conversion.

The --original-field-name-delimiter option works with --snake-case-field to specify the delimiter used in original field names. This is useful when field names contain delimiters like spaces or hyphens that should be treated as word boundaries during snake_case conversion.

Option relationships:

  • Requires: --snake-case-field enabled - --original-field-name-delimiter can not be used without --snake-case-field.

Usage

datamodel-codegen --input space_field_enum.json --snake-case-field --original-field-name-delimiter " " # (1)!
  1. --original-field-name-delimiter - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "SpaceIF": {
      "$ref": "#/definitions/SpaceIF"
    }
  },
  "definitions": {
    "SpaceIF": {
      "type": "string",
      "enum": [
        "Space Field"
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  space_field_enum.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, Field


class SpaceIF(Enum):
    space_field = 'Space Field'


class Model(BaseModel):
    space_if: SpaceIF | None = Field(None, alias='SpaceIF')

--read-length-keywords-by-type

Read the string and the array keywords for their own kind only, as JSON Schema does.

minLength, maxLength and pattern apply to strings and minItems, maxItems and uniqueItems to arrays. Without this option a declared array writes minLength and maxLength as its item counts (Field(max_length=2) on a list, which rejects ["a", "b", "c"], valid for the schema) and a declared string minItems and maxItems as its length (constr(max_length=2), which rejects "abc"). With it such a keyword is left out silently, as minimum beside a string is: at a property, an item, a map value, a root, the branches of a union and a schema with items but no type, also where an override writes the field as another type.

Usage

datamodel-codegen --input length_keywords_by_type.json --use-annotated --read-length-keywords-by-type # (1)!
  1. --read-length-keywords-by-type - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "LengthKeywordsByType",
  "type": "object",
  "properties": {
    "tags": {"type": "array", "items": {"type": "string"}, "minLength": 1, "maxLength": 2},
    "counted": {"type": "array", "items": {"type": "string"}, "maxItems": 3, "maxLength": 2},
    "code": {"type": "string", "minItems": 1, "maxItems": 2},
    "either": {"type": ["string", "array"], "items": {"type": "integer"}, "maxLength": 2},
    "branch": {"maxLength": 3, "anyOf": [{"type": "array", "items": {"type": "integer"}}, {"type": "string"}]},
    "untyped": {"items": {"type": "integer"}, "maxLength": 2},
    "nested": {"type": "array", "items": {"type": "array", "items": {"type": "integer"}, "maxLength": 1}},
    "by_key": {
      "type": "object",
      "additionalProperties": {"type": "array", "items": {"type": "integer"}, "maxLength": 1}
    },
    "letters": {"type": "array", "items": {"enum": ["xx", "yy"]}, "maxLength": 2},
    "letter_seq": {
      "type": "array",
      "items": {"enum": ["xx", "yy"]},
      "maxLength": 2,
      "x-python-type": "Sequence[str]"
    },
    "as_text": {"type": "array", "items": {"type": "integer"}, "maxLength": 2, "x-python-type": "str"},
    "count": {"type": "integer", "format": "int64", "maxLength": 2},
    "short": {"$ref": "#/$defs/Short"},
    "named": {"$ref": "#/$defs/Name", "minItems": 1}
  },
  "$defs": {
    "Short": {"type": "array", "items": {"type": "integer"}, "maxLength": 2},
    "Name": {"type": "string"}
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  length_keywords_by_type.json

from __future__ import annotations

from collections.abc import Sequence
from enum import Enum
from typing import Annotated

from pydantic import BaseModel, Field, RootModel
from typing_extensions import TypeAliasType

EitherString = TypeAliasType("EitherString", Annotated[str, Field(max_length=2)])


class Branch(RootModel[list[int]]):
    root: list[int]


class Branch1(RootModel[str]):
    root: Annotated[str, Field(max_length=3)]


class NestedItem(RootModel[list[int]]):
    root: list[int]


class Letter(Enum):
    xx = 'xx'
    yy = 'yy'


class LetterSeqEnum(Enum):
    xx = 'xx'
    yy = 'yy'


class Short(RootModel[list[int]]):
    root: list[int]


class Name(RootModel[str]):
    root: str


class LengthKeywordsByType(BaseModel):
    tags: list[str] | None = None
    counted: Annotated[list[str] | None, Field(max_length=3)] = None
    code: str | None = None
    either: EitherString | list[int] | None = None
    branch: Branch | Branch1 | None = None
    untyped: list[int] | None = None
    nested: list[NestedItem] | None = None
    by_key: dict[str, list[int]] | None = None
    letters: list[Letter] | None = None
    letter_seq: Sequence[LetterSeqEnum] | None = None
    as_text: str | None = None
    count: int | None = None
    short: Short | None = None
    named: str | None = None
# generated by datamodel-codegen:
#   filename:  length_keywords_by_type.json

from __future__ import annotations

from collections.abc import Sequence
from enum import Enum
from typing import Annotated

from pydantic import BaseModel, Field, RootModel
from typing_extensions import TypeAliasType

EitherString = TypeAliasType("EitherString", Annotated[str, Field(max_length=2)])


class Branch(RootModel[list[int]]):
    root: Annotated[list[int], Field(max_length=3)]


class Branch1(RootModel[str]):
    root: Annotated[str, Field(max_length=3)]


class NestedItem(RootModel[list[int]]):
    root: Annotated[list[int], Field(max_length=1)]


class Letter(Enum):
    xx = 'xx'
    yy = 'yy'


class LetterSeqEnum(Enum):
    xx = 'xx'
    yy = 'yy'


class Short(RootModel[list[int]]):
    root: Annotated[list[int], Field(max_length=2)]


class Name(RootModel[str]):
    root: str


class LengthKeywordsByType(BaseModel):
    tags: Annotated[list[str] | None, Field(max_length=2, min_length=1)] = None
    counted: Annotated[list[str] | None, Field(max_length=3)] = None
    code: Annotated[str | None, Field(max_length=2, min_length=1)] = None
    either: EitherString | list[int] | None = None
    branch: Branch | Branch1 | None = None
    untyped: Annotated[list[int] | None, Field(max_length=2)] = None
    nested: list[NestedItem] | None = None
    by_key: dict[str, list[int]] | None = None
    letters: Annotated[list[Letter] | None, Field(max_length=2)] = None
    letter_seq: Annotated[Sequence[LetterSeqEnum] | None, Field(max_length=2)] = None
    as_text: Annotated[str | None, Field(max_length=2)] = None
    count: int | None = None
    short: Short | None = None
    named: Annotated[str | None, Field(min_length=1)] = None

--read-msgspec-union-bounds-exactly

Decide the bounds of the int member of a msgspec union on the bounds the schema writes.

msgspec decodes every JSON integer as the int member of a union that has a float member too, so the int member goes without its Meta bounds when they would reject an integer the float member accepts. Without this option the float member's bound is read as the float it is written as, which past 2**53 is another integer: {"type": "number", "minimum": 1234567890123456700} reads as 1234567890123456768, so Annotated[int, Meta(ge=1234567890123456750)] keeps its bound and rejects 1234567890123456720, which the number branch accepts. With it the check reads the bounds the schema writes, exactly (msgspec.Struct output only).

Usage

datamodel-codegen --input union_integer_bounds.json --output-model-type msgspec.Struct --read-msgspec-union-bounds-exactly # (1)!
  1. --read-msgspec-union-bounds-exactly - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Model",
  "type": "object",
  "properties": {
    "wide": {
      "anyOf": [
        {"type": "integer", "minimum": 1234567890123456750},
        {"type": "number", "minimum": 1234567890123456700}
      ]
    },
    "narrow": {
      "anyOf": [
        {"type": "integer", "minimum": 1234567890123456769},
        {"type": "number", "minimum": 1234567890123456770}
      ]
    },
    "small": {
      "anyOf": [
        {"type": "integer", "minimum": 10},
        {"type": "number", "minimum": 5.5}
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  union_integer_bounds.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Annotated, TypeAlias

from msgspec import UNSET, Meta, Struct, UnsetType

Wide: TypeAlias = Annotated[int, Meta(ge=1234567890123456750)]


Wide1: TypeAlias = Annotated[float, Meta(ge=1.2345678901234568e+18)]


Narrow: TypeAlias = Annotated[int, Meta(ge=1234567890123456769)]


Narrow1: TypeAlias = Annotated[float, Meta(ge=1.2345678901234568e+18)]


Small: TypeAlias = Annotated[int, Meta(ge=10)]


Small1: TypeAlias = Annotated[float, Meta(ge=5.5)]


class Model(Struct):
    wide: int | Wide1 | UnsetType = UNSET
    narrow: Narrow | Narrow1 | UnsetType = UNSET
    small: int | Small1 | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  union_integer_bounds.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Annotated, TypeAlias

from msgspec import UNSET, Meta, Struct, UnsetType

Wide: TypeAlias = Annotated[int, Meta(ge=1234567890123456750)]


Wide1: TypeAlias = Annotated[float, Meta(ge=1.2345678901234568e+18)]


Narrow: TypeAlias = Annotated[int, Meta(ge=1234567890123456769)]


Narrow1: TypeAlias = Annotated[float, Meta(ge=1.2345678901234568e+18)]


Small: TypeAlias = Annotated[int, Meta(ge=10)]


Small1: TypeAlias = Annotated[float, Meta(ge=5.5)]


class Model(Struct):
    wide: Wide | Wide1 | UnsetType = UNSET
    narrow: int | Narrow1 | UnsetType = UNSET
    small: int | Small1 | UnsetType = UNSET

--remove-special-field-name-prefix

Remove the special prefix from field names.

The --remove-special-field-name-prefix flag configures the code generation behavior.

Usage

datamodel-codegen --input special_prefix_model.json --remove-special-field-name-prefix # (1)!
  1. --remove-special-field-name-prefix - the option documented here
Examples

Input Schema:

{
    "$id": "schema_v2.json",
    "$schema": "http://json-schema.org/schema#",

    "type": "object",
    "properties": {
        "@id": {
            "type": "string",
            "format": "uri",
            "pattern": "^http.*$",
            "title": "Id must be presesnt and must be a URI"
        },
        "@type": { "type": "string" },
        "@+!type": { "type": "string" },
        "@-!type": { "type": "string" },
        "profile": { "type": "string" }
    },
    "required": ["@id", "@type"]
}

Output:

# generated by datamodel-codegen:
#   filename:  special_prefix_model.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import AnyUrl, BaseModel, Field


class Model(BaseModel):
    id: AnyUrl = Field(..., alias='@id', title='Id must be presesnt and must be a URI')
    type: str = Field(..., alias='@type')
    type_1: str | None = Field(None, alias='@+!type')
    type_2: str | None = Field(None, alias='@-!type')
    profile: str | None = None

--serialization-aliases

Apply custom Pydantic v2 serialization aliases via inline JSON or a JSON file path.

The --serialization-aliases option lets Pydantic v2 models keep input aliases or validation aliases while using separate output-only names for serialization.

Usage

datamodel-codegen --input serialization_aliases.json --aliases aliases/serialization_aliases.json --serialization-aliases aliases/serialization_aliases_output.json --output-model-type pydantic_v2.BaseModel # (1)!
  1. --serialization-aliases - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Messaging",
  "type": "object",
  "definitions": {
    "SendMessageV2": {
      "type": "object",
      "properties": {
        "textMessage": {
          "type": "string"
        }
      },
      "required": ["textMessage"]
    },
    "OtherMessage": {
      "type": "object",
      "properties": {
        "other-name": {
          "type": "string"
        }
      },
      "required": ["other-name"]
    },
    "SameNameMessage": {
      "type": "object",
      "properties": {
        "same-name": {
          "type": "string"
        }
      },
      "required": ["same-name"]
    },
    "RequiredOnlyMessage": {
      "type": "object",
      "allOf": [
        {
          "type": "object",
          "properties": {
            "known-name": {
              "type": "string"
            }
          },
          "required": [
            "known-name",
            "missing-required",
            "plain-missing",
            "allof-unmapped"
          ]
        }
      ],
      "required": [
        "known-name",
        "missing-required",
        "plain-missing",
        "allof-unmapped"
      ]
    },
    "RequiredOnlyGrandBase": {
      "type": "object",
      "properties": {
        "grand-name": {
          "type": "integer"
        },
        "bare-name": {}
      },
      "required": ["grand-name", "bare-name"]
    },
    "RequiredOnlyBase": {
      "type": "object",
      "properties": {
        "base-name": {
          "type": "string"
        }
      },
      "allOf": [
        {
          "$ref": "#/definitions/RequiredOnlyGrandBase"
        }
      ],
      "required": ["base-name"]
    },
    "RequiredOnlyRefMessage": {
      "type": "object",
      "properties": {
        "own-name": {
          "type": "string"
        }
      },
      "allOf": [
        {
          "$ref": "#/definitions/RequiredOnlyBase"
        }
      ],
      "required": [
        "own-name",
        "grand-name",
        "bare-name",
        "ignored-missing",
        "ref-missing-required",
        "ref-plain-missing"
      ]
    },
    "RequiredOnlyEmptyAllOfBase": {
      "type": "object",
      "allOf": [
        {
          "type": "object"
        }
      ]
    },
    "RequiredOnlyEmptyAllOfMessage": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/definitions/RequiredOnlyEmptyAllOfBase"
        }
      ],
      "required": ["empty-missing"]
    },
    "RequiredOnlyRecursiveEmptyGrandBase": {
      "type": "object",
      "properties": {
        "unrelated-name": {
          "type": "string"
        }
      }
    },
    "RequiredOnlyRecursiveEmptyBase": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/definitions/RequiredOnlyRecursiveEmptyGrandBase"
        }
      ]
    },
    "RequiredOnlyRecursiveEmptyMessage": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/definitions/RequiredOnlyRecursiveEmptyBase"
        }
      ],
      "required": ["recursive-missing"]
    }
  },
  "properties": {
    "send": {
      "$ref": "#/definitions/SendMessageV2"
    },
    "other": {
      "$ref": "#/definitions/OtherMessage"
    },
    "same": {
      "$ref": "#/definitions/SameNameMessage"
    },
    "requiredOnly": {
      "$ref": "#/definitions/RequiredOnlyMessage"
    },
    "requiredOnlyRef": {
      "$ref": "#/definitions/RequiredOnlyRefMessage"
    },
    "requiredOnlyEmptyAllOf": {
      "$ref": "#/definitions/RequiredOnlyEmptyAllOfMessage"
    },
    "requiredOnlyRecursiveEmpty": {
      "$ref": "#/definitions/RequiredOnlyRecursiveEmptyMessage"
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  serialization_aliases.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Any

from pydantic import AliasChoices, BaseModel, Field


class SendMessageV2(BaseModel):
    message: str = Field(
        ...,
        serialization_alias='messageText',
        validation_alias=AliasChoices('textMessage', 'message', 'text'),
    )


class OtherMessage(BaseModel):
    other_name: str = Field(..., alias='other-name', serialization_alias='otherName')


class SameNameMessage(BaseModel):
    same_name: str = Field(..., alias='same-name', serialization_alias='same_name')


class RequiredOnlyMessage(BaseModel):
    known_name: str = Field(..., alias='known-name')
    missingRequiredInput: Any = Field(
        ...,
        serialization_alias='missingRequired',
        validation_alias=AliasChoices('missing-required', 'missingRequiredInput'),
    )
    plainMissingInput: Any = Field(
        ..., alias='plain-missing', serialization_alias='plainMissing'
    )
    allof_unmapped: Any = Field(..., alias='allof-unmapped')


class RequiredOnlyGrandBase(BaseModel):
    grand_name: int = Field(..., alias='grand-name')
    bare_name: Any = Field(..., alias='bare-name')


class RequiredOnlyBase(RequiredOnlyGrandBase):
    base_name: str = Field(..., alias='base-name')


class RequiredOnlyRefMessage(RequiredOnlyBase):
    own_name: str = Field(..., alias='own-name')
    grand_name: int = Field(
        ...,
        serialization_alias='grandName',
        validation_alias=AliasChoices('grand-name', 'grandInput'),
    )
    bare_name: Any = Field(..., alias='bare-name', serialization_alias='bareName')
    ignored_missing: Any = Field(..., alias='ignored-missing')
    refMissingInput: Any = Field(
        ...,
        serialization_alias='refMissingRequired',
        validation_alias=AliasChoices('ref-missing-required', 'refMissingInput'),
    )
    refPlainMissingInput: Any = Field(
        ..., alias='ref-plain-missing', serialization_alias='refPlainMissing'
    )


class RequiredOnlyEmptyAllOfBase(BaseModel):
    pass


class RequiredOnlyEmptyAllOfMessage(RequiredOnlyEmptyAllOfBase):
    emptyMissingInput: Any = Field(
        ...,
        serialization_alias='emptyMissing',
        validation_alias=AliasChoices('empty-missing', 'emptyMissingInput'),
    )


class RequiredOnlyRecursiveEmptyGrandBase(BaseModel):
    unrelated_name: str | None = Field(None, alias='unrelated-name')


class RequiredOnlyRecursiveEmptyBase(RequiredOnlyRecursiveEmptyGrandBase):
    pass


class RequiredOnlyRecursiveEmptyMessage(RequiredOnlyRecursiveEmptyBase):
    recursiveMissingInput: Any = Field(
        ..., alias='recursive-missing', serialization_alias='recursiveMissing'
    )


class Messaging(BaseModel):
    send: SendMessageV2 | None = None
    other: OtherMessage | None = None
    same: SameNameMessage | None = None
    requiredOnly: RequiredOnlyMessage | None = None
    requiredOnlyRef: RequiredOnlyRefMessage | None = None
    requiredOnlyEmptyAllOf: RequiredOnlyEmptyAllOfMessage | None = None
    requiredOnlyRecursiveEmpty: RequiredOnlyRecursiveEmptyMessage | None = None

--set-default-enum-member

Use the legacy flag for deserializing enum defaults.

The --set-default-enum-member flag is deprecated. Use --deserialize-default-values enum instead.

Deprecated: --set-default-enum-member is deprecated. Use --deserialize-default-values enum instead.

Usage

datamodel-codegen --input duplicate_enum.json --reuse-model --set-default-enum-member # (1)!
  1. --set-default-enum-member - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "title": "User",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "animal": {
      "type": "string",
      "enum": [
        "dog",
        "cat",
        "snake"
      ],
      "default": "dog"
    },
    "pet": {
      "type": "string",
      "enum": [
        "dog",
        "cat",
        "snake"
      ],
      "default": "cat"
    },
    "redistribute": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "static",
          "connected"
        ]
      }
    }
  },
  "definitions": {
    "redistribute": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "static",
          "connected"
        ]
      },
      "description": "Redistribute type for routes."
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  duplicate_enum.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, Field, RootModel


class Animal(Enum):
    dog = 'dog'
    cat = 'cat'
    snake = 'snake'


class RedistributeEnum(Enum):
    static = 'static'
    connected = 'connected'


class User(BaseModel):
    name: str | None = None
    animal: Animal | None = Animal.dog
    pet: Animal | None = Animal.cat
    redistribute: list[RedistributeEnum] | None = None


class Redistribute(RootModel[list[RedistributeEnum]]):
    root: list[RedistributeEnum] = Field(
        ..., description='Redistribute type for routes.'
    )

--snake-case-field

Convert field names to snake_case format.

The --snake-case-field flag converts camelCase or PascalCase field names to snake_case format in the generated Python code, following Python naming conventions (PEP 8).

Related: --capitalize-enum-members

Usage

datamodel-codegen --input invalid_enum_name.json --snake-case-field # (1)!
  1. --snake-case-field - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "InvalidEnum",
  "type": "string",
  "enum": [
    "1 value",
    " space",
    "*- special",
    "schema",
    "MRO",
    "mro"
  ]
}

Output:

# generated by datamodel-codegen:
#   filename:  invalid_enum_name.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum


class InvalidEnum(Enum):
    field_1_value = '1 value'
    field_space = ' space'
    field___special = '*- special'
    schema = 'schema'
    mro_1 = 'MRO'
    mro_ = 'mro'

--special-field-name-prefix

Prefix to add to special field names (like reserved keywords).

The --special-field-name-prefix flag configures the code generation behavior.

Usage

datamodel-codegen --input special_enum.json --special-field-name-prefix special # (1)!
  1. --special-field-name-prefix - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "string",
  "enum": [
    true,
    false,
    "",
    "\n",
    "\r\n",
    "\t",
    "\\x08",
    null,
    "\\"
  ]
}

Output:

# generated by datamodel-codegen:
#   filename:  special_enum.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum

from pydantic import RootModel


class ModelEnum(Enum):
    True_ = True
    False_ = False
    special_ = ''
    special__1 = '\n'
    special__ = '\r\n'
    special__2 = '\t'
    special_x08 = '\\x08'
    special__3 = '\\'


class Model(RootModel[ModelEnum | None]):
    root: ModelEnum | None = None

--use-attribute-docstrings

Generate field descriptions as attribute docstrings instead of Field descriptions.

The --use-attribute-docstrings flag places field descriptions in Python docstring format (PEP 224 attribute docstrings) rather than in Field(..., description=...). This provides better IDE support for hovering over attributes. Requires --use-field-description to be enabled.

Related: --use-field-description

Usage

datamodel-codegen --input use_attribute_docstrings_test.json --output-model-type pydantic_v2.BaseModel --use-field-description --use-attribute-docstrings # (1)!
  1. --use-attribute-docstrings - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Person",
  "properties": {
    "name": {
      "type": "string",
      "description": "The person's full name"
    },
    "age": {
      "type": "integer",
      "description": "The person's age in years"
    }
  },
  "required": ["name"]
}

Output:

# generated by datamodel-codegen:
#   filename:  use_attribute_docstrings_test.json
#   timestamp: 1985-10-26T08:21:00+00:00

from __future__ import annotations

from pydantic import BaseModel, ConfigDict


class Person(BaseModel):
    model_config = ConfigDict(
        use_attribute_docstrings=True,
    )
    name: str
    """
    The person's full name
    """
    age: int | None = None
    """
    The person's age in years
    """

--use-enum-values-in-discriminator

Use enum values in discriminator mappings for union types.

The --use-enum-values-in-discriminator flag configures the code generation behavior.

Usage

datamodel-codegen --input discriminator_enum.yaml --use-enum-values-in-discriminator --output-model-type pydantic_v2.BaseModel # (1)!
  1. --use-enum-values-in-discriminator - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
components:
  schemas:
    Request:
      oneOf:
        - $ref: '#/components/schemas/RequestV1'
        - $ref: '#/components/schemas/RequestV2'
      discriminator:
        propertyName: version
        mapping:
          v1: '#/components/schemas/RequestV1'
          v2: '#/components/schemas/RequestV2'

    RequestVersionEnum:
      type: string
      description: this is not included!
      title: no title!
      enum:
        - v1
        - v2
    RequestBase:
      properties:
        version:
          $ref: '#/components/schemas/RequestVersionEnum'
      required:
        - version

    RequestV1:
      allOf:
        - $ref: '#/components/schemas/RequestBase'
      properties:
        request_id:
          type: string
          title: test title
          description: there is description
      required:
        - request_id
    RequestV2:
      allOf:
        - $ref: '#/components/schemas/RequestBase'

Output:

# generated by datamodel-codegen:
#   filename:  discriminator_enum.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum
from typing import Literal

from pydantic import BaseModel, Field, RootModel


class RequestVersionEnum(Enum):
    v1 = 'v1'
    v2 = 'v2'


class RequestBase(BaseModel):
    version: RequestVersionEnum


class RequestV1(RequestBase):
    request_id: str = Field(..., description='there is description', title='test title')
    version: Literal[RequestVersionEnum.v1, 'v1']


class RequestV2(RequestBase):
    version: Literal[RequestVersionEnum.v2, 'v2']


class Request(RootModel[RequestV1 | RequestV2]):
    root: RequestV1 | RequestV2 = Field(..., discriminator='version')

--use-field-description

Include schema descriptions as Field docstrings.

The --use-field-description flag extracts the description property from schema fields and includes them as docstrings or Field descriptions in the generated models, preserving documentation from the original schema.

Related: --use-inline-field-description, --use-schema-description

Usage

datamodel-codegen --input type_alias.json --use-type-alias --use-field-description # (1)!
  1. --use-field-description - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    x-amazon-apigateway-integration:
      uri:
        Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
      passthroughBehavior: when_no_templates
      httpMethod: POST
      type: aws_proxy
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          default: 1
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Users:
      type: array
      items:
        required:
          - id
          - name
        properties:
          id:
            type: integer
            format: int64
          name:
            type: string
          tag:
            type: string
    Id:
      type: string
    Rules:
      type: array
      items:
        type: string
    Error:
      description: "error result.\nNow with multi-line docstrings."
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    apis:
      type: array
      items:
        type: object
        properties:
          apiKey:
            type: string
            description: "To be used as a dataset parameter value.\nNow also with multi-line docstrings."
          apiVersionNumber:
            type: string
            description: To be used as a version parameter value
          apiUrl:
            type: string
            format: uri
            description: "The URL describing the dataset's fields"
          apiDocumentationUrl:
            type: string
            format: uri
            description: A URL to the API console for each API
    Event:
      type: object
      description: Event object
      properties:
        name:
          type: string
    Result:
        type: object
        properties:
          event:
            $ref: '#/components/schemas/Event'

Output:

# generated by datamodel-codegen:
#   filename:  api_multiline_docstrings.yaml
#   timestamp: 2022-11-11T00:00:00+00:00

from __future__ import annotations

from pydantic import AnyUrl, BaseModel, RootModel


class Pet(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Pets(RootModel[list[Pet]]):
    root: list[Pet]


class User(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Users(RootModel[list[User]]):
    root: list[User]


class Id(RootModel[str]):
    root: str


class Rules(RootModel[list[str]]):
    root: list[str]


class Error(BaseModel):
    code: int
    message: str


class Api(BaseModel):
    apiKey: str | None = None
    """
    To be used as a dataset parameter value.
    Now also with multi-line docstrings.
    """
    apiVersionNumber: str | None = None
    """
    To be used as a version parameter value
    """
    apiUrl: AnyUrl | None = None
    """
    The URL describing the dataset's fields
    """
    apiDocumentationUrl: AnyUrl | None = None
    """
    A URL to the API console for each API
    """


class Apis(RootModel[list[Api]]):
    root: list[Api]


class Event(BaseModel):
    name: str | None = None


class Result(BaseModel):
    event: Event | None = None

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "SimpleString": {
      "type": "string"
    },
    "UnionType": {
      "anyOf": [
        {"type": "string"},
        {"type": "integer"}
      ]
    },
    "ArrayType": {
      "type": "array",
      "items": {"type": "string"}
    },
    "AnnotatedType": {
      "title": "MyAnnotatedType",
      "description": "An annotated union type",
      "anyOf": [
        {"type": "string"},
        {"type": "boolean"}
      ]
    },
    "ModelWithTypeAliasField": {
      "type": "object",
      "properties": {
        "simple_field": {"$ref": "#/definitions/SimpleString"},
        "union_field": {"$ref": "#/definitions/UnionType"},
        "array_field": {"$ref": "#/definitions/ArrayType"},
        "annotated_field": {"$ref": "#/definitions/AnnotatedType"}
      }
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  type_alias.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Annotated, Any

from pydantic import BaseModel, Field
from typing_extensions import TypeAliasType

Model = TypeAliasType("Model", Any)


SimpleString = TypeAliasType("SimpleString", str)


UnionType = TypeAliasType("UnionType", str | int)


ArrayType = TypeAliasType("ArrayType", list[str])


AnnotatedType = TypeAliasType(
    "AnnotatedType", Annotated[str | bool, Field(..., title='MyAnnotatedType')]
)
"""
An annotated union type
"""


class ModelWithTypeAliasField(BaseModel):
    simple_field: SimpleString | None = None
    union_field: UnionType | None = None
    array_field: ArrayType | None = None
    annotated_field: AnnotatedType | None = None

--use-field-description-example

Add field examples to docstrings.

The --use-field-description-example flag adds the example or examples property from schema fields as docstrings. This provides documentation that is visible in IDE intellisense.

Related: --use-field-description, --use-inline-field-description

Usage

datamodel-codegen --input extras.json --use-field-description-example # (1)!
  1. --use-field-description-example - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Extras",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "normal key",
      "key1": 123,
      "key2": 456,
      "$exclude": 123,
      "invalid-key-1": "abc",
      "-invalid+key_2": "efg",
      "$comment": "comment",
      "$id": "#name",
      "register": "hij",
      "schema": "klm",
      "x-repr": true,
      "x-abc": true,
      "example": "example",
      "readOnly": true
    },
    "age": {
      "type": "integer",
      "example": 12,
      "writeOnly": true,
      "examples": [
        13,
        20
      ]
    },
    "status": {
      "type": "string",
      "examples": [
        "active"
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  extras.json
#   timestamp: 2022-11-11T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class Extras(BaseModel):
    name: str | None = Field(None, description='normal key', examples=['example'])
    """
    Example: 'example'
    """
    age: int | None = Field(None, examples=[13, 20], json_schema_extra={'example': 12})
    """
    Examples:
    - 13
    - 20
    """
    status: str | None = Field(None, examples=['active'])
    """
    Example: 'active'
    """

--use-inline-field-description

Add field descriptions as inline comments.

The --use-inline-field-description flag adds the description property from schema fields as inline comments after each field definition. This provides documentation without using Field() wrappers.

Related: --use-field-description, --use-schema-description

Usage

datamodel-codegen --input api_multiline_docstrings.yaml --use-inline-field-description # (1)!
  1. --use-inline-field-description - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    x-amazon-apigateway-integration:
      uri:
        Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
      passthroughBehavior: when_no_templates
      httpMethod: POST
      type: aws_proxy
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          default: 1
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Users:
      type: array
      items:
        required:
          - id
          - name
        properties:
          id:
            type: integer
            format: int64
          name:
            type: string
          tag:
            type: string
    Id:
      type: string
    Rules:
      type: array
      items:
        type: string
    Error:
      description: "error result.\nNow with multi-line docstrings."
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    apis:
      type: array
      items:
        type: object
        properties:
          apiKey:
            type: string
            description: "To be used as a dataset parameter value.\nNow also with multi-line docstrings."
          apiVersionNumber:
            type: string
            description: To be used as a version parameter value
          apiUrl:
            type: string
            format: uri
            description: "The URL describing the dataset's fields"
          apiDocumentationUrl:
            type: string
            format: uri
            description: A URL to the API console for each API
    Event:
      type: object
      description: Event object
      properties:
        name:
          type: string
    Result:
        type: object
        properties:
          event:
            $ref: '#/components/schemas/Event'

Output:

# generated by datamodel-codegen:
#   filename:  api_multiline_docstrings.yaml
#   timestamp: 2022-11-11T00:00:00+00:00

from __future__ import annotations

from pydantic import AnyUrl, BaseModel, Field, RootModel


class Pet(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Pets(RootModel[list[Pet]]):
    root: list[Pet]


class User(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Users(RootModel[list[User]]):
    root: list[User]


class Id(RootModel[str]):
    root: str


class Rules(RootModel[list[str]]):
    root: list[str]


class Error(BaseModel):
    code: int
    message: str


class Api(BaseModel):
    apiKey: str | None = Field(
        None,
        description='To be used as a dataset parameter value.\nNow also with multi-line docstrings.',
    )
    """
    To be used as a dataset parameter value.
    Now also with multi-line docstrings.
    """

    apiVersionNumber: str | None = Field(
        None, description='To be used as a version parameter value'
    )
    """To be used as a version parameter value"""

    apiUrl: AnyUrl | None = Field(
        None, description="The URL describing the dataset's fields"
    )
    """The URL describing the dataset's fields"""

    apiDocumentationUrl: AnyUrl | None = Field(
        None, description='A URL to the API console for each API'
    )
    """A URL to the API console for each API"""


class Apis(RootModel[list[Api]]):
    root: list[Api]


class Event(BaseModel):
    name: str | None = None


class Result(BaseModel):
    event: Event | None = None

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "MultilineDescriptionWithExample",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "User name.\nThis is a multi-line description.",
      "example": "John Doe"
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  multiline_description_with_example.json
#   timestamp: 2022-11-11T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class MultilineDescriptionWithExample(BaseModel):
    name: str | None = Field(
        None,
        description='User name.\nThis is a multi-line description.',
        examples=['John Doe'],
    )
    """
    User name.
    This is a multi-line description.

    Example: 'John Doe'
    """

--use-one-model-per-ref-site

Give an object $ref with sibling keywords one model per place it is written.

A $ref beside other keywords is parsed as its target merged with them. Without this option the merged object is parsed at the path that reaches it, and the copy of each such $ref its target holds is parsed again below it, so a chain of N definitions whose next is a $ref to the next one beside required gives N(N-1)/2 site models (Next, Next1, ..., where the copies of one place, such as Next1 and Next4, validate the same documents), one nested parse per hop, which stops with "Schema nesting is too deep" for a long chain. With it each place such a $ref is written, with the $dynamicAnchor bindings of its dynamic scope, gets one model, which every unchanged copy of the place shares, parsed from a worklist without nesting: N-1 site models beside the N definitions. The field that holds the $ref keeps its own required, default and alias. Where --read-only-write-only-model-type request-response splits the models, the model of a place is parsed where it is first met, so a chain still nests one parse per hop.

Usage

datamodel-codegen --input ref_site_chain.json --use-one-model-per-ref-site # (1)!
  1. --use-one-model-per-ref-site - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Chain",
  "$ref": "#/$defs/Link0",
  "$defs": {
    "Link0": {
      "type": "object",
      "properties": {
        "v": {
          "type": "integer"
        },
        "next": {
          "$ref": "#/$defs/Link1",
          "required": [
            "v"
          ],
          "description": "link 0"
        }
      }
    },
    "Link1": {
      "type": "object",
      "properties": {
        "v": {
          "type": "integer"
        },
        "next": {
          "$ref": "#/$defs/Link2",
          "required": [
            "v"
          ],
          "description": "link 1"
        }
      }
    },
    "Link2": {
      "type": "object",
      "properties": {
        "v": {
          "type": "integer"
        },
        "next": {
          "$ref": "#/$defs/Link3",
          "required": [
            "v"
          ],
          "description": "link 2"
        }
      }
    },
    "Link3": {
      "type": "object",
      "properties": {
        "v": {
          "type": "integer"
        },
        "next": {
          "$ref": "#/$defs/Link4",
          "required": [
            "v"
          ],
          "description": "link 3"
        }
      }
    },
    "Link4": {
      "type": "object",
      "properties": {
        "v": {
          "type": "integer"
        }
      }
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  ref_site_chain.json

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class Next3(BaseModel):
    v: int


class Link3(BaseModel):
    v: int | None = None
    next: Next3 | None = Field(None, description='link 3')


class Link4(BaseModel):
    v: int | None = None


class Next2(BaseModel):
    v: int
    next: Next3 | None = Field(None, description='link 3')


class Link2(BaseModel):
    v: int | None = None
    next: Next2 | None = Field(None, description='link 2')


class Next1(BaseModel):
    v: int
    next: Next2 | None = Field(None, description='link 2')


class Link1(BaseModel):
    v: int | None = None
    next: Next1 | None = Field(None, description='link 1')


class Next(BaseModel):
    v: int
    next: Next1 | None = Field(None, description='link 1')


class Link0(BaseModel):
    v: int | None = None
    next: Next | None = Field(None, description='link 0')


class Chain(RootModel[Link0]):
    root: Link0 = Field(..., title='Chain')
# generated by datamodel-codegen:
#   filename:  ref_site_chain.json

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class Next3(BaseModel):
    v: int


class Next2(BaseModel):
    v: int
    next: Next3 | None = Field(None, description='link 3')


class Next1(BaseModel):
    v: int
    next: Next2 | None = Field(None, description='link 2')


class Next(BaseModel):
    v: int
    next: Next1 | None = Field(None, description='link 1')


class Link0(BaseModel):
    v: int | None = None
    next: Next | None = Field(None, description='link 0')


class Next6(BaseModel):
    v: int


class Next5(BaseModel):
    v: int
    next: Next6 | None = Field(None, description='link 3')


class Next4(BaseModel):
    v: int
    next: Next5 | None = Field(None, description='link 2')


class Link1(BaseModel):
    v: int | None = None
    next: Next4 | None = Field(None, description='link 1')


class Next8(BaseModel):
    v: int


class Next7(BaseModel):
    v: int
    next: Next8 | None = Field(None, description='link 3')


class Link2(BaseModel):
    v: int | None = None
    next: Next7 | None = Field(None, description='link 2')


class Next9(BaseModel):
    v: int


class Link3(BaseModel):
    v: int | None = None
    next: Next9 | None = Field(None, description='link 3')


class Link4(BaseModel):
    v: int | None = None


class Chain(RootModel[Link0]):
    root: Link0 = Field(..., title='Chain')

--use-schema-description

Use schema description as class docstring.

The --use-schema-description flag extracts the description property from schema definitions and adds it as a docstring to the generated class. This is useful for preserving documentation from your schema in the generated code.

Related: --use-field-description, --use-inline-field-description

Usage

datamodel-codegen --input api_multiline_docstrings.yaml --use-schema-description # (1)!
  1. --use-schema-description - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
                x-amazon-apigateway-integration:
                  uri:
                    Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
                  passthroughBehavior: when_no_templates
                  httpMethod: POST
                  type: aws_proxy
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    x-amazon-apigateway-integration:
      uri:
        Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations
      passthroughBehavior: when_no_templates
      httpMethod: POST
      type: aws_proxy
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          default: 1
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Users:
      type: array
      items:
        required:
          - id
          - name
        properties:
          id:
            type: integer
            format: int64
          name:
            type: string
          tag:
            type: string
    Id:
      type: string
    Rules:
      type: array
      items:
        type: string
    Error:
      description: "error result.\nNow with multi-line docstrings."
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    apis:
      type: array
      items:
        type: object
        properties:
          apiKey:
            type: string
            description: "To be used as a dataset parameter value.\nNow also with multi-line docstrings."
          apiVersionNumber:
            type: string
            description: To be used as a version parameter value
          apiUrl:
            type: string
            format: uri
            description: "The URL describing the dataset's fields"
          apiDocumentationUrl:
            type: string
            format: uri
            description: A URL to the API console for each API
    Event:
      type: object
      description: Event object
      properties:
        name:
          type: string
    Result:
        type: object
        properties:
          event:
            $ref: '#/components/schemas/Event'

Output:

# generated by datamodel-codegen:
#   filename:  api_multiline_docstrings.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import AnyUrl, BaseModel, Field, RootModel


class Pet(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Pets(RootModel[list[Pet]]):
    root: list[Pet]


class User(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Users(RootModel[list[User]]):
    root: list[User]


class Id(RootModel[str]):
    root: str


class Rules(RootModel[list[str]]):
    root: list[str]


class Error(BaseModel):
    """
    error result.
    Now with multi-line docstrings.
    """

    code: int
    message: str


class Api(BaseModel):
    apiKey: str | None = Field(
        None,
        description='To be used as a dataset parameter value.\nNow also with multi-line docstrings.',
    )
    apiVersionNumber: str | None = Field(
        None, description='To be used as a version parameter value'
    )
    apiUrl: AnyUrl | None = Field(
        None, description="The URL describing the dataset's fields"
    )
    apiDocumentationUrl: AnyUrl | None = Field(
        None, description='A URL to the API console for each API'
    )


class Apis(RootModel[list[Api]]):
    root: list[Api]


class Event(BaseModel):
    """
    Event object
    """

    name: str | None = None


class Result(BaseModel):
    event: Event | None = None

--use-serialization-alias

Use serialization_alias instead of alias for field aliasing (Pydantic v2 only).

The --use-serialization-alias flag changes field aliasing to use serialization_alias instead of alias. This allows setting values using the Pythonic field name while serializing to the original JSON property name.

Usage

datamodel-codegen --input no_alias.json --use-serialization-alias --output-model-type pydantic_v2.BaseModel # (1)!
  1. --use-serialization-alias - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Person",
  "type": "object",
  "properties": {
    "first-name": {
      "type": "string"
    },
    "last-name": {
      "type": "string"
    },
    "email_address": {
      "type": "string"
    }
  },
  "required": ["first-name", "last-name"]
}

Output:

# generated by datamodel-codegen:
#   filename:  no_alias.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class Person(BaseModel):
    first_name: str = Field(..., serialization_alias='first-name')
    last_name: str = Field(..., serialization_alias='last-name')
    email_address: str | None = None
# generated by datamodel-codegen:
#   filename:  no_alias.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field


class Person(BaseModel):
    first_name: str = Field(..., alias='first-name')
    last_name: str = Field(..., alias='last-name')
    email_address: str | None = None

--use-single-line-docstring

Emit short docstrings on a single line.

The --use-single-line-docstring flag formats docstrings that fit on one line as compact single-line docstrings while keeping the historical multi-line format as the default.

Related: --use-field-description, --use-schema-description

Usage

datamodel-codegen --input person.json --use-field-description --use-single-line-docstring # (1)!
  1. --use-single-line-docstring - the option documented here
Examples

Input Schema:

{
  "$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", "null"],
      "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"
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  person.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field, conint


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

--use-site-models-for-constrained-refs

Give an allOf of $ref members whose other parts add assertions its own model.

Without the option such an allOf is written as the referenced type, which leaves out the constraints, the enum values or the type its other parts add: allOf: [{$ref: Quantity}], maximum: 10 accepts 11. With the option the site gets its own model of the values all parts admit (conint(ge=1, le=10)), named after the site, and an allOf of enum references gets an enum of the members they share. The referenced type stays where it enforces what the parts enforce together in the output (dataclasses and TypedDict check no constraints, so only types and literals count there), and msgspec writes the added constraints beside the reference where its Meta takes them. A model-level --type-overrides entry of the referenced model applies to its site models too.

Usage

datamodel-codegen --input site_models_for_constrained_refs.json --use-site-models-for-constrained-refs # (1)!
  1. --use-site-models-for-constrained-refs - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Order",
  "type": "object",
  "properties": {
    "quantity": {
      "allOf": [
        {
          "$ref": "#/$defs/Quantity"
        }
      ],
      "maximum": 10
    },
    "sizes": {
      "type": "array",
      "items": {
        "allOf": [
          {
            "$ref": "#/$defs/Size"
          },
          {
            "enum": [
              "m",
              "l"
            ]
          }
        ]
      }
    }
  },
  "$defs": {
    "Quantity": {
      "type": "integer",
      "minimum": 1
    },
    "Size": {
      "type": "string",
      "enum": [
        "s",
        "m",
        "l"
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  site_models_for_constrained_refs.json

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, RootModel, conint


class Quantity1(RootModel[conint(ge=1, le=10)]):
    root: conint(ge=1, le=10)


class Size2(Enum):
    m = 'm'
    l = 'l'


class Order(BaseModel):
    quantity: Quantity1 | None = None
    sizes: list[Size2] | None = None


class Quantity(RootModel[conint(ge=1)]):
    root: conint(ge=1)


class Size(Enum):
    s = 's'
    m = 'm'
    l = 'l'
# generated by datamodel-codegen:
#   filename:  site_models_for_constrained_refs.json

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, RootModel, conint


class Quantity(RootModel[conint(ge=1)]):
    root: conint(ge=1)


class Size(Enum):
    s = 's'
    m = 'm'
    l = 'l'


class Order(BaseModel):
    quantity: Quantity | None = None
    sizes: list[Size] | None = None

--use-tag-as-union-variant-name

Name inline oneOf/anyOf branch models after their tag: what --infer-union-variant-names does, skipping tags whose class names collide, plus single-branch unions (type: "exec" -> LocalShellActionExec) and single-key branches ({"granular": ...} -> AskForApprovalGranular).

--infer-union-variant-names needs at least two branches with distinct literals on one field, so a union with one tagged branch keeps a position-based name that changes once a second branch is added, and a branch tagged by its only key, as in externally tagged enums, is never named. --use-tag-as-union-variant-name gives the names --infer-union-variant-names gives wherever that option names a union with distinct class names, and in the other unions also names:

  • the branches after a literal field that only one branch carries or that the key branches below lack, picked like --infer-union-variant-names picks it (the discriminator property first, then property order) except that a field the union schema itself fixes to a single literal is skipped; a branch that is a union itself is not named this way;
  • a key branch after its key: its only own property (one the union schema does not declare), required and not a single literal, when the branch has no oneOf/anyOf and no allOf of its own that adds properties (the union schema's allOf is shared by every branch), and fixes no field the union declares without a literal to a single literal, unless the union is one branch beside null.

String enum branches and branches with several untagged properties keep position-based names. Names are compared as the class names they become, so foo-bar and fooBar (both FooBar) collide: a literal field whose names collide is skipped for the next one, and literal names win over key names, so a key name that collides with a literal name or another key name is dropped and its branch keeps a position-based name.

Under --naming-strategy parent-prefixed or full-path, a model in the value of a branch named after its key is named as if the branch were not in its path, so the key is not repeated: the branch ItemEditedChangesFieldValue holds ItemEditedFieldValue, not ItemEditedChangesFieldValueFieldValue, numbered like any other name when another model has it.

Branches default --infer-union-variant-names --use-tag-as-union-variant-name
Several branches, distinct type literals Pet1, Pet2 PetCat, PetDog PetCat, PetDog
Single branch (type: "exec") LocalShellAction1 LocalShellAction1 LocalShellActionExec
Single-key branch ({"granular": ...}) AskForApproval2 AskForApproval2 AskForApprovalGranular

Related: --infer-union-variant-names, --use-title-as-name

Usage

datamodel-codegen --input use_tag_as_union_variant_name.json --use-tag-as-union-variant-name # (1)!
  1. --use-tag-as-union-variant-name - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Session",
  "type": "object",
  "required": ["pet", "action", "approval"],
  "properties": {
    "pet": {"$ref": "#/definitions/Pet"},
    "action": {"$ref": "#/definitions/LocalShellAction"},
    "approval": {"$ref": "#/definitions/AskForApproval"}
  },
  "definitions": {
    "Pet": {
      "oneOf": [
        {
          "type": "object",
          "required": ["type", "meows"],
          "properties": {
            "type": {"const": "cat"},
            "meows": {"type": "boolean"}
          }
        },
        {
          "type": "object",
          "required": ["type", "barks"],
          "properties": {
            "type": {"const": "dog"},
            "barks": {"type": "boolean"}
          }
        }
      ]
    },
    "LocalShellAction": {
      "oneOf": [
        {
          "type": "object",
          "required": ["command", "type"],
          "properties": {
            "command": {"type": "array", "items": {"type": "string"}},
            "type": {"type": "string", "enum": ["exec"]}
          }
        }
      ]
    },
    "AskForApproval": {
      "oneOf": [
        {"type": "string", "enum": ["untrusted", "never"]},
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["granular"],
          "properties": {
            "granular": {
              "type": "object",
              "required": ["sandbox"],
              "properties": {
                "sandbox": {"type": "boolean"}
              }
            }
          }
        }
      ]
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  use_tag_as_union_variant_name.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum
from typing import Literal

from pydantic import BaseModel, ConfigDict, RootModel


class PetCat(BaseModel):
    type: Literal['cat']
    meows: bool


class PetDog(BaseModel):
    type: Literal['dog']
    barks: bool


class Pet(RootModel[PetCat | PetDog]):
    root: PetCat | PetDog


class Type(Enum):
    exec = 'exec'


class LocalShellActionExec(BaseModel):
    command: list[str]
    type: Type


class LocalShellAction(RootModel[LocalShellActionExec]):
    root: LocalShellActionExec


class AskForApproval1(Enum):
    untrusted = 'untrusted'
    never = 'never'


class Granular(BaseModel):
    sandbox: bool


class AskForApprovalGranular(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    granular: Granular


class AskForApproval(RootModel[AskForApproval1 | AskForApprovalGranular]):
    root: AskForApproval1 | AskForApprovalGranular


class Session(BaseModel):
    pet: Pet
    action: LocalShellAction
    approval: AskForApproval
# generated by datamodel-codegen:
#   filename:  use_tag_as_union_variant_name.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum
from typing import Literal

from pydantic import BaseModel, ConfigDict, RootModel


class Pet1(BaseModel):
    type: Literal['cat']
    meows: bool


class Pet2(BaseModel):
    type: Literal['dog']
    barks: bool


class Pet(RootModel[Pet1 | Pet2]):
    root: Pet1 | Pet2


class Type(Enum):
    exec = 'exec'


class LocalShellAction1(BaseModel):
    command: list[str]
    type: Type


class LocalShellAction(RootModel[LocalShellAction1]):
    root: LocalShellAction1


class AskForApproval1(Enum):
    untrusted = 'untrusted'
    never = 'never'


class Granular(BaseModel):
    sandbox: bool


class AskForApproval2(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    granular: Granular


class AskForApproval(RootModel[AskForApproval1 | AskForApproval2]):
    root: AskForApproval1 | AskForApproval2


class Session(BaseModel):
    pet: Pet
    action: LocalShellAction
    approval: AskForApproval

--use-title-as-name

Use schema title as the generated class name.

The --use-title-as-name flag uses the title property from the schema as the class name instead of deriving it from the property name or path. This is useful when schemas have descriptive titles that should be preserved.

Related: --class-name

Usage

datamodel-codegen --input titles.json --use-title-as-name # (1)!
  1. --use-title-as-name - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "ProcessingStatus": {
      "title": "Processing Status Title",
      "enum": [
        "COMPLETED",
        "PENDING",
        "FAILED"
      ],
      "type": "string",
      "description": "The processing status"
    },
    "kind": {
      "type": "string"
    },
    "ExtendedProcessingTask": {
      "title": "Extended Processing Task Title",
      "oneOf": [
        {
          "$ref": "#"
        },
        {
          "type": "object",
          "title": "NestedCommentTitle",
          "properties": {
            "comment": {
              "type": "string"
            }
          }
        }
      ]
    },
    "ExtendedProcessingTasks": {
      "title": "Extended Processing Tasks Title",
      "type": "array",
      "items": [
        {
          "$ref": "#/definitions/ExtendedProcessingTask"
        }
      ]
    },
    "ProcessingTask": {
      "title": "Processing Task Title",
      "type": "object",
      "properties": {
        "processing_status_union": {
          "title": "Processing Status Union Title",
          "oneOf": [
            {
              "title": "Processing Status Detail",
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "description": {
                  "type": "string"
                }
              }
            },
            {
              "$ref": "#/definitions/ExtendedProcessingTask"
            },
            {
              "$ref": "#/definitions/ProcessingStatus"
            }
          ],
          "default": "COMPLETED"
        },
        "processing_status": {
          "$ref": "#/definitions/ProcessingStatus",
          "default": "COMPLETED"
        },
        "name": {
          "type": "string"
        },
        "kind": {
          "$ref": "#/definitions/kind"
        }
      }
    }
  },
  "title": "Processing Tasks Title",
  "type": "array",
      "items": [
        {
          "$ref": "#/definitions/ProcessingTask"
        }
      ]
}

Output:

# generated by datamodel-codegen:
#   filename:  titles.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, Field, RootModel


class ProcessingStatusTitle(Enum):
    COMPLETED = 'COMPLETED'
    PENDING = 'PENDING'
    FAILED = 'FAILED'


class Kind(RootModel[str]):
    root: str


class NestedCommentTitle(BaseModel):
    comment: str | None = None


class ProcessingStatusDetail(BaseModel):
    id: int | None = None
    description: str | None = None


class ProcessingTaskTitle(BaseModel):
    processing_status_union: ProcessingStatusUnionTitle | None = Field(
        'COMPLETED', title='Processing Status Union Title', validate_default=True
    )
    processing_status: ProcessingStatusTitle | None = 'COMPLETED'
    name: str | None = None
    kind: Kind | None = None


class ProcessingTasksTitle(RootModel[list[ProcessingTaskTitle]]):
    root: list[ProcessingTaskTitle] = Field(..., title='Processing Tasks Title')


class ExtendedProcessingTask(RootModel[ProcessingTasksTitle | NestedCommentTitle]):
    root: ProcessingTasksTitle | NestedCommentTitle = Field(
        ..., title='Extended Processing Task Title'
    )


class ExtendedProcessingTasksTitle(RootModel[list[ExtendedProcessingTask]]):
    root: list[ExtendedProcessingTask] = Field(
        ..., title='Extended Processing Tasks Title'
    )


class ProcessingStatusUnionTitle(
    RootModel[ProcessingStatusDetail | ExtendedProcessingTask | ProcessingStatusTitle]
):
    root: ProcessingStatusDetail | ExtendedProcessingTask | ProcessingStatusTitle = (
        Field('COMPLETED', title='Processing Status Union Title', validate_default=True)
    )


ProcessingTaskTitle.model_rebuild()