Skip to content

🏗️ Model Customization

📋 Options

Option Description
--alias-generator Use a Pydantic v2 alias generator in model_config.
--allow-extra-fields Allow extra fields in generated Pydantic models (extra='allo...
--allow-leading-underscore-class-name Allow an explicitly specified root class name to start with ...
--allow-population-by-field-name Allow Pydantic model population by field name (not just alia...
--apply-field-options-to-every-field Give the fields that leave out some field options the ones o...
--base-class Specify a custom base class for generated models.
--base-class-map Specify different base classes for specific models via JSON ...
--class-name Override the auto-generated class name with a custom name.
--class-name-affix-scope Control which classes receive the prefix/suffix.
--class-name-prefix Add a prefix to all generated class names.
--class-name-suffix Add a suffix to all generated class names.
--collapse-constrained-root-models-as-annotated Inline a constrained string root model into a union or a con...
--collapse-reuse-models Collapse duplicate models by replacing references instead of...
--collapse-root-models Inline root model definitions instead of creating separate w...
--collapse-root-models-name-strategy Select which name to keep when collapsing root models with o...
--collapse-shared-parent-wrappers Collapse a parent-strategy wrapper in every model that refer...
--dataclass-arguments Customize dataclass decorator arguments via JSON dictionary.
--duplicate-name-suffix Customize suffix for duplicate model names.
--enable-faux-immutability Enable faux immutability in Pydantic models (frozen=True).
--force-optional Force all fields to be Optional regardless of required statu...
--frozen-dataclasses Generate frozen dataclasses with optional keyword-only field...
--keep-constrained-root-models-in-every-container Keep constrained root models named in every container of a h...
--keep-defaults-of-inherited-required-fields Keep under --use-default the default of a property only an...
--keep-enum-literal-aliases Keep a named enum written as a Literal type alias named unde...
--keep-false-dataclass-arguments Write every dataclass decorator argument set to false.
--keep-field-defaults-off-branch-roots Leave a property's default off the root models extracted fro...
--keep-model-order Keep generated model order deterministic while respecting de...
--keep-reference-null-on-collapsed-root-models Keep the null of a root model that admits null where `--coll...
--keep-reference-null-on-merged-models Keep the null a reference's schema admits when its model is ...
--keep-self-referencing-array-items Keep the items of an array whose items name the array itself...
--keep-shared-members-on-collapsed-root-models Keep each member of a root type that collapse inlined at sev...
--keyword-only Generate dataclasses with keyword-only fields (Python 3.10+)...
--merge-message-trait-headers Give an AsyncAPI message the headers of all its traits, merg...
--model-extra-keys Add model-level schema extensions to ConfigDict json_schema_...
--model-extra-keys-without-x-prefix Strip x- prefix from model-level schema extensions and add t...
--model-name-map Rename generated model classes from a JSON mapping.
--name-converted-payloads-by-message Name a converted payload that names no type of its own after...
--naming-strategy Choose how models are named and how duplicate model names ar...
--omit-incomplete-model-defaults Write a property whose object default lacks required fields ...
--omit-redundant-reference-null Do not write None again at a reference to a model that holds...
--order-constructor-fields-by Order constructor fields by final names or by written defaul...
--output-model-type Select the output model type (Pydantic v2, Pydantic v2 datac...
--parent-scoped-naming Namespace models by their parent scope to avoid naming confl...
--pin-aliases-with-alias-generator Decide a field's alias by the alias generator its model appl...
--read-nullable-beside-type-list Write the null that nullable: true declares beside a `type...
--remove-unused-models-beside-type-overrides Remove the unused models from a module that a model-level `-...
--reuse-model Reuse identical model definitions instead of generating dupl...
--reuse-scope Scope for model reuse detection (root or tree).
--singularize-last-word-of-item-names Name the item model of an array by singularizing only the la...
--skip-root-model Skip generation of root model when schema contains nested de...
--strict-nullable Treat default field as a non-nullable field.
--strip-default-none Remove fields with None as default value from generated mode...
--tag-msgspec-by-payload-name Tag the structs of a msgspec discriminated union with the pr...
--target-pydantic-version Target Pydantic version for generated code compatibility.
--target-python-version Target Python version for generated code syntax and imports.
--union-mode Union mode for combining anyOf/oneOf schemas (smart or left_...
--use-default Use default values from schema in generated models.
--use-default-factory-for-optional-nested-models Generate default_factory for optional nested model fields.
--use-default-kwarg Use default= keyword argument instead of positional argument...
--use-duplicate-name-suffix-for-every-collision Give the --duplicate-name-suffix suffix to every model ren...
--use-frozen-field Generate frozen (immutable) field definitions for readOnly p...
--use-generic-base-class Generate a shared base class with model configuration to avo...
--use-missing-sentinel Use Pydantic's MISSING sentinel for unset optional BaseModel...
--use-msgspec-forbid-unknown-fields Reject the unknown fields of a msgspec Struct whose schema a...
--use-msgspec-meta-for-map-keys Check the keys of a msgspec map whose keys propertyNames or ...
--use-msgspec-nullable-enum-alias Write a msgspec.Struct enum that lists null as an Enum and a...
--use-msgspec-tagged-unions Write a msgspec.Struct discriminated union as tagged structs...
--use-one-literal-as-default Use single literal value as default when enum has only one o...
--use-root-model-sequence-interface Make non-null sequence-like Pydantic v2 RootModel classes im...
--use-serialize-as-any Wrap fields with subtypes in Pydantic's SerializeAsAny.
--use-serialize-as-any-for-every-subclass Wrap a field in SerializeAsAny when any subclass of its mode...
--use-subclass-enum Generate typed Enum subclasses for enums with specific field...

🍳 Recipes

Target Pydantic v2 on modern Python

Set the output model family and Python/Pydantic compatibility targets together.

Options: --output-model-type, --target-python-version, --target-pydantic-version

Deduplicate reusable schemas

Reuse equivalent models and tune the scope or root-model behavior when schemas repeat.

Options: --reuse-model, --reuse-scope, --collapse-root-models


--alias-generator

Use a Pydantic v2 alias generator in model_config.

The --alias-generator option emits a per-model ConfigDict alias generator for Pydantic v2 BaseModel output and omits matching per-field aliases. With --target-pydantic-version 2 every field alias is written out, so aliases do not depend on the generator of the installed Pydantic.

Related: --output-model-type, --snake-case-field

Usage

datamodel-codegen --input alias_generator.json --snake-case-field --alias-generator to_camel --output-model-type pydantic_v2.BaseModel # (1)!
  1. --alias-generator - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "AliasGeneratorModel",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    },
    "foo_bar": {
      "type": "string"
    },
    "weird-url": {
      "type": "integer"
    }
  },
  "required": ["firstName", "foo_bar", "weird-url"]
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel


class AliasGeneratorModel(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
        alias_generator=to_camel,
    )
    first_name: str
    last_name: str | None = None
    foo_bar: str = Field(..., alias='foo_bar')
    weird_url: int = Field(..., alias='weird-url')

--allow-extra-fields

Allow extra fields in generated Pydantic models (extra='allow').

The --allow-extra-fields flag configures the code generation behavior.

Deprecated: --allow-extra-fields is deprecated. Use --extra-fields=allow instead.

Option relationships:

Usage

datamodel-codegen --input api.yaml --allow-extra-fields # (1)!
  1. --allow-extra-fields - 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 pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel


class Pet(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    id: int
    name: str
    tag: str | None = None


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


class User(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    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):
    model_config = ConfigDict(
        extra='allow',
    )
    code: int
    message: str


class Api(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    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):
    model_config = ConfigDict(
        extra='allow',
    )
    name: str | None = None


class Result(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    event: Event | None = None

--allow-leading-underscore-class-name

Allow an explicitly specified root class name to start with an underscore.

By default, leading underscores in class names are normalized to avoid private model names. Use --allow-leading-underscore-class-name together with an explicit --class-name when you need the generated root model to preserve that name exactly.

Related: --class-name

Usage

datamodel-codegen --input class_name_affix.json --class-name __ParsedModel --allow-leading-underscore-class-name --disable-timestamp # (1)!
  1. --allow-leading-underscore-class-name - the option documented here
Examples

Input Schema:

{
  "type": "object",
  "properties": {
    "status": {
      "$ref": "#/$defs/Status"
    },
    "item": {
      "$ref": "#/$defs/Item"
    }
  },
  "$defs": {
    "Status": {
      "type": "string",
      "enum": ["active", "inactive"]
    },
    "Item": {
      "type": "object",
      "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"}
      }
    }
  }
}

Output:

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

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel


class Status(Enum):
    active = 'active'
    inactive = 'inactive'


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


class __ParsedModel(BaseModel):
    status: Status | None = None
    item: Item | None = None

--allow-population-by-field-name

Allow Pydantic model population by field name (not just alias).

The --allow-population-by-field-name flag configures the code generation behavior.

Usage

datamodel-codegen --input api.yaml --allow-population-by-field-name # (1)!
  1. --allow-population-by-field-name - 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 pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel


class Pet(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    id: int
    name: str
    tag: str | None = None


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


class User(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    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):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    code: int
    message: str


class Api(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    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):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    name: str | None = None


class Result(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,
    )
    event: Event | None = None

--apply-field-options-to-every-field

Give the fields that leave out some field options the ones others take.

A GraphQL field, a property whose schema is true or false, a required name that no property declares and the tag field a discriminator appends to a variant leave out some field options, such as --use-default-kwarg, --use-annotated and --use-default-factory-for-optional-nested-models, which the other fields of their model take, so one option gives different fields in one model. With this option they take them too: owner_id: Annotated[Any, Field(alias='owner-id')] beside display_name: Annotated[str, Field(alias='display-name')]. The root field of a root model is not one of them: under --force-optional and --use-default-kwarg a discriminated union root still writes root: Cat | Dog | None = Field(None, discriminator='kind').

Usage

datamodel-codegen --input field_options_every_field.yaml --use-annotated --apply-field-options-to-every-field # (1)!
  1. --apply-field-options-to-every-field - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info: {title: Field options on every field, version: "1"}
paths: {}
components:
  schemas:
    Flags:
      type: object
      properties:
        any-value: true
        other-value: {}
    Base:
      type: object
      properties:
        id: {type: string}
    Child:
      allOf:
        - $ref: '#/components/schemas/Base'
        - properties:
            display-name: {type: string}
          required: [display-name, owner-id, id]
    Pet:
      oneOf: [{$ref: '#/components/schemas/Dog'}, {$ref: '#/components/schemas/Cat'}]
      discriminator: {propertyName: pet-type, mapping: {dog: '#/components/schemas/Dog', cat: '#/components/schemas/Cat'}}
    Dog: {type: object, properties: {bark: {type: string}}}
    Cat: {type: object, properties: {meow: {type: string}}}
    Owner:
      type: object
      properties:
        address: {$ref: '#/components/schemas/Address'}
        pet: {$ref: '#/components/schemas/Pet'}
    Address:
      type: object
      properties:
        city: {type: string}

Output:

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

from __future__ import annotations

from typing import Annotated, Any, Literal

from pydantic import BaseModel, Field, RootModel


class Flags(BaseModel):
    any_value: Annotated[Any | None, Field(alias='any-value')] = None
    other_value: Annotated[Any | None, Field(alias='other-value')] = None


class Base(BaseModel):
    id: str | None = None


class Child(Base):
    display_name: Annotated[str, Field(alias='display-name')]
    owner_id: Annotated[Any, Field(alias='owner-id')]
    id: str


class Dog(BaseModel):
    bark: str | None = None
    pet_type: Annotated[Literal['dog'], Field(alias='pet-type')]


class Cat(BaseModel):
    meow: str | None = None
    pet_type: Annotated[Literal['cat'], Field(alias='pet-type')]


class Address(BaseModel):
    city: str | None = None


class Pet(RootModel[Dog | Cat]):
    root: Annotated[Dog | Cat, Field(discriminator='pet_type')]


class Owner(BaseModel):
    address: Address | None = None
    pet: Pet | None = None
# generated by datamodel-codegen:
#   filename:  field_options_every_field.yaml

from __future__ import annotations

from typing import Annotated, Any, Literal

from pydantic import BaseModel, Field, RootModel


class Flags(BaseModel):
    any_value: Annotated[Any | None, Field(alias='any-value')] = None
    other_value: Annotated[Any | None, Field(alias='other-value')] = None


class Base(BaseModel):
    id: str | None = None


class Child(Base):
    display_name: Annotated[str, Field(alias='display-name')]
    owner_id: Any = Field(..., alias='owner-id')
    id: str


class Dog(BaseModel):
    bark: str | None = None
    pet_type: Literal['dog'] = Field(..., alias='pet-type')


class Cat(BaseModel):
    meow: str | None = None
    pet_type: Literal['cat'] = Field(..., alias='pet-type')


class Address(BaseModel):
    city: str | None = None


class Pet(RootModel[Dog | Cat]):
    root: Annotated[Dog | Cat, Field(discriminator='pet_type')]


class Owner(BaseModel):
    address: Address | None = None
    pet: Pet | None = None

--base-class

Specify a custom base class for generated models.

The --base-class flag configures the code generation behavior.

Usage

datamodel-codegen --input api.yaml --base-class custom_module.Base # (1)!
  1. --base-class - 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 pydantic import AnyUrl, Field, RootModel

from custom_module import Base


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


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


class User(Base):
    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(Base):
    code: int
    message: str


class Api(Base):
    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(Base):
    name: str | None = None


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

--base-class-map

Specify different base classes for specific models via JSON mapping.

The --base-class-map option allows you to assign different base classes to specific models. This is useful when you want selective base class inheritance, for example, applying custom base classes only to specific models while leaving others with the default BaseModel.

Priority: --base-class-map > customBasePath (schema extension) > --base-class

You can specify either a single base class as a string, or multiple base classes (mixins) as a list:

  • Single: {"Person": "custom.bases.PersonBase"}
  • Multiple: {"User": ["mixins.AuditMixin", "mixins.TimestampMixin"]}

You can pass the mapping either inline as JSON or as a path to a JSON file.

When using multiple base classes, the specified classes are used directly without adding BaseModel. Ensure your mixins inherit from BaseModel if needed.

Related: --base-class

Usage

datamodel-codegen --input base_class_map.json --base-class-map '{"Person": "custom.bases.PersonBase", "Animal": "custom.bases.AnimalBase"}' # (1)!
  1. --base-class-map - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "Person": {
      "type": "object",
      "properties": {
        "name": {"type": "string"}
      }
    },
    "Animal": {
      "type": "object",
      "properties": {
        "species": {"type": "string"}
      }
    },
    "Car": {
      "type": "object",
      "properties": {
        "model": {"type": "string"}
      }
    }
  }
}

Output:

from __future__ import annotations

from typing import Any

from custom.bases import AnimalBase, PersonBase
from pydantic import BaseModel, RootModel


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


class Person(PersonBase):
    name: str | None = None


class Animal(AnimalBase):
    species: str | None = None


class Car(BaseModel):
    model: str | None = None

--class-name

Override the auto-generated class name with a custom name.

The --class-name option allows you to specify a custom class name for the generated model. This is useful when the schema title is invalid as a Python class name (e.g., starts with a number) or when you want to use a different naming convention than what's in the schema.

Usage

datamodel-codegen --input invalid_model_name.json --class-name ValidModelName # (1)!
  1. --class-name - the option documented here
Examples

Input Schema:

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

Output:

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

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field, conint


class ValidModelName(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)

--class-name-affix-scope

Control which classes receive the prefix/suffix.

The --class-name-affix-scope option controls which types of classes receive the prefix or suffix specified by --class-name-prefix or --class-name-suffix: - 'all': Apply to all classes (models and enums) - this is the default - 'models': Apply only to model classes (BaseModel, dataclass, TypedDict, etc.) - 'enums': Apply only to enum classes

Related: --class-name-prefix, --class-name-suffix

Usage

datamodel-codegen --input class_name_affix.json --class-name-suffix Schema --class-name-affix-scope models # (1)!
  1. --class-name-affix-scope - the option documented here
Examples

Input Schema:

{
  "type": "object",
  "properties": {
    "status": {
      "$ref": "#/$defs/Status"
    },
    "item": {
      "$ref": "#/$defs/Item"
    }
  },
  "$defs": {
    "Status": {
      "type": "string",
      "enum": ["active", "inactive"]
    },
    "Item": {
      "type": "object",
      "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"}
      }
    }
  }
}

Output:

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

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel


class Status(Enum):
    active = 'active'
    inactive = 'inactive'


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


class ModelSchemaSchema(BaseModel):
    status: Status | None = None
    item: ItemSchema | None = None

--class-name-prefix

Add a prefix to all generated class names.

The --class-name-prefix option allows you to add a prefix to all generated class names, including both models and enums. This is useful for namespacing generated code or avoiding conflicts with existing classes.

Related: --class-name-affix-scope, --class-name-suffix

Usage

datamodel-codegen --input class_name_affix.json --class-name-prefix Api # (1)!
  1. --class-name-prefix - the option documented here
Examples

Input Schema:

{
  "type": "object",
  "properties": {
    "status": {
      "$ref": "#/$defs/Status"
    },
    "item": {
      "$ref": "#/$defs/Item"
    }
  },
  "$defs": {
    "Status": {
      "type": "string",
      "enum": ["active", "inactive"]
    },
    "Item": {
      "type": "object",
      "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"}
      }
    }
  }
}

Output:

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

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel


class ApiStatus(Enum):
    active = 'active'
    inactive = 'inactive'


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


class ApiModel(BaseModel):
    status: ApiStatus | None = None
    item: ApiItem | None = None

--class-name-suffix

Add a suffix to all generated class names.

The --class-name-suffix option allows you to add a suffix to all generated class names, including both models and enums. This is useful for distinguishing generated classes (e.g., adding 'Schema' or 'Model' suffix).

Related: --class-name-affix-scope, --class-name-prefix

Usage

datamodel-codegen --input class_name_affix.json --class-name-suffix Schema # (1)!
  1. --class-name-suffix - the option documented here
Examples

Input Schema:

{
  "type": "object",
  "properties": {
    "status": {
      "$ref": "#/$defs/Status"
    },
    "item": {
      "$ref": "#/$defs/Item"
    }
  },
  "$defs": {
    "Status": {
      "type": "string",
      "enum": ["active", "inactive"]
    },
    "Item": {
      "type": "object",
      "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"}
      }
    }
  }
}

Output:

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

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel


class StatusSchema(Enum):
    active = 'active'
    inactive = 'inactive'


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


class ModelSchema(BaseModel):
    status: StatusSchema | None = None
    item: ItemSchema | None = None

--collapse-constrained-root-models-as-annotated

Inline a constrained string root model into a union or a container as Annotated.

Under --use-annotated (which turns on --field-constraints), a string with constraints inside a union, such as the string branch of an "ID or object" property, or as the items or values of a container, becomes a root model of its own, which --collapse-root-models keeps named there, as Field() arguments of the holder's field could not carry its constraints: account: Account | AccountModel with Account(RootModel[str]), which also takes a name a component may want. With this option collapse inlines it in place as a string type that writes its constraints in Annotated (account: AccountModel | Annotated[str, StringConstraints(max_length=8)], tags: list[Annotated[str, StringConstraints(max_length=3)]]), so the member keeps its constraints and parses as a str. Root models of other types, and output models whose types write no constraints (msgspec, dataclasses), keep the root model.

Usage

datamodel-codegen --input collapse_constrained_string_members.yaml --use-annotated --collapse-root-models --use-unique-items-as-set --collapse-constrained-root-models-as-annotated # (1)!
  1. --collapse-constrained-root-models-as-annotated - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info: {title: constrained string members, version: "1"}
paths: {}
components:
  schemas:
    Fee:
      type: object
      properties:
        account:
          description: ID or object
          anyOf:
            - type: string
              maxLength: 8
            - $ref: '#/components/schemas/Account'
        tags:
          type: array
          items:
            type: string
            maxLength: 3
        labels:
          type: array
          uniqueItems: true
          items:
            type: string
            minLength: 1
        codes:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Code'
        slug:
          anyOf:
            - type: string
              pattern: '^(?!x)[a-z]+$'
            - type: integer
              minimum: 0
        notes:
          type: array
          items:
            $ref: '#/components/schemas/Note'
    Account:
      type: object
      properties:
        id: {type: string}
    Code:
      type: string
      maxLength: 2
    Note:
      type: [string, 'null']
      maxLength: 4

Output:

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

from __future__ import annotations

from typing import Annotated

from pydantic import BaseModel, ConfigDict, Field, RootModel, StringConstraints


class Slug1(RootModel[int]):
    root: Annotated[int, Field(ge=0)]


class AccountModel(BaseModel):
    id: str | None = None


class Note(RootModel[str | None]):
    root: Annotated[str | None, Field(max_length=4)]


class Fee(BaseModel):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    account: Annotated[
        AccountModel | Annotated[str, StringConstraints(max_length=8)] | None,
        Field(description='ID or object'),
    ] = None
    tags: list[Annotated[str, StringConstraints(max_length=3)]] | None = None
    labels: set[Annotated[str, StringConstraints(min_length=1)]] | None = None
    codes: dict[str, Annotated[str, StringConstraints(max_length=2)]] | None = None
    slug: Slug1 | Annotated[str, StringConstraints(pattern=r'^(?!x)[a-z]+$')] | None = (
        None
    )
    notes: list[Note | None] | None = None
# generated by datamodel-codegen:
#   filename:  collapse_constrained_string_members.yaml

from __future__ import annotations

from typing import Annotated

from pydantic import BaseModel, ConfigDict, Field, RootModel


class Account(RootModel[str]):
    root: Annotated[str, Field(description='ID or object', max_length=8)]


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


class Slug(RootModel[str]):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    root: Annotated[str, Field(pattern='^(?!x)[a-z]+$')]


class Slug1(RootModel[int]):
    root: Annotated[int, Field(ge=0)]


class AccountModel(BaseModel):
    id: str | None = None


class Code(RootModel[str]):
    root: Annotated[str, Field(max_length=2)]


class Note(RootModel[str | None]):
    root: Annotated[str | None, Field(max_length=4)]


class Fee(BaseModel):
    account: Annotated[
        Account | AccountModel | None, Field(description='ID or object')
    ] = None
    tags: list[Tag] | None = None
    labels: set[str] | None = None
    codes: dict[str, Code] | None = None
    slug: Slug | Slug1 | None = None
    notes: list[Note | None] | None = None

--collapse-reuse-models

Collapse duplicate models by replacing references instead of inheritance.

The --collapse-reuse-models flag, when used with --reuse-model, eliminates redundant empty subclasses (e.g., class Foo(Bar): pass) by replacing all references to duplicate models with the canonical model.

Related: --reuse-model

Usage

datamodel-codegen --input duplicate_models.json --reuse-model --collapse-reuse-models # (1)!
  1. --collapse-reuse-models - the option documented here
Examples

Input Schema:

{
    "Arm Right": {
        "Joint 1": 5,
        "Joint 2": 3,
        "Joint 3": 66
    },
    "Arm Left": {
        "Joint 1": 55,
        "Joint 2": 13,
        "Joint 3": 6
    },
    "Head": {
        "Joint 1": 10
    }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field


class ArmRight(BaseModel):
    Joint_1: int = Field(..., alias='Joint 1')
    Joint_2: int = Field(..., alias='Joint 2')
    Joint_3: int = Field(..., alias='Joint 3')


class Head(BaseModel):
    Joint_1: int = Field(..., alias='Joint 1')


class Model(BaseModel):
    Arm_Right: ArmRight = Field(..., alias='Arm Right')
    Arm_Left: ArmRight = Field(..., alias='Arm Left')
    Head_1: Head = Field(..., alias='Head')

--collapse-root-models

Inline root model definitions instead of creating separate wrapper classes.

The --collapse-root-models option generates simpler output by inlining root models directly instead of creating separate wrapper types. This shows how different output model types (Pydantic v2, dataclass, TypedDict, msgspec) handle const fields.

See also: Model Reuse and Deduplication

Usage

datamodel-codegen --input const.yaml --collapse-root-models # (1)!
  1. --collapse-root-models - the option documented here
Examples

Input Schema:

openapi: '3.0.2'
components:
  schemas:
    ApiVersion:
      description: The version of this API
      type: string
      const: v1
    Api:
      type: object
      required:
        - version
      properties:
        version:
          $ref: "#/components/schemas/ApiVersion"

Output:

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

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field


class Api(BaseModel):
    version: Literal['v1'] = Field(..., description='The version of this API')
# generated by datamodel-codegen:
#   filename:  const.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal


@dataclass
class Api:
    version: Literal['v1']
# generated by datamodel-codegen:
#   filename:  const.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Literal, TypedDict


class Api(TypedDict):
    version: Literal['v1']
# generated by datamodel-codegen:
#   filename:  const.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Annotated, Literal

from msgspec import Meta, Struct


class Api(Struct):
    version: Annotated[Literal['v1'], Meta(description='The version of this API')]
# generated by datamodel-codegen:
#   filename:  const.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field, RootModel


class ApiVersion(RootModel[Literal['v1']]):
    root: Literal['v1'] = Field(..., description='The version of this API')


class Api(BaseModel):
    version: ApiVersion

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "field": {
      "anyOf": [
        {"$ref": "#/$defs/NullType1"},
        {"$ref": "#/$defs/NullType2"}
      ]
    }
  },
  "$defs": {
    "NullType1": {
      "type": "null"
    },
    "NullType2": {
      "type": "null"
    }
  }
}

Output:

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

from __future__ import annotations

from typing import Any

from pydantic import BaseModel


class Model(BaseModel):
    field: Any = None

--collapse-root-models-name-strategy

Select which name to keep when collapsing root models with object references.

The --collapse-root-models-name-strategy option controls naming when collapsing root models. 'child' keeps the inner model's name, 'parent' uses the wrapper's name.

Related: --collapse-root-models

Option relationships:

  • Requires: --collapse-root-models enabled - --collapse-root-models-name-strategy requires --collapse-root-models.

Usage

datamodel-codegen --input collapse_root_models_name_strategy_child.json --collapse-root-models --collapse-root-models-name-strategy child # (1)!
  1. --collapse-root-models-name-strategy - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "metadata": {
      "$ref": "#/$defs/ISectionBlockMetadata"
    }
  },
  "$defs": {
    "ISectionBlockMetadata": {
      "$ref": "#/$defs/FieldType2"
    },
    "FieldType2": {
      "type": "object",
      "properties": {
        "asText": {
          "type": "string"
        }
      },
      "required": ["asText"]
    }
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel


class FieldType2(BaseModel):
    asText: str


class Model(BaseModel):
    metadata: FieldType2 | None = None

--collapse-shared-parent-wrappers

Collapse a parent-strategy wrapper in every model that references it.

Under --collapse-root-models-name-strategy parent the inner model takes the name of a wrapper (a root model whose root is a $ref) at the wrapper's first holder. Where --field-type-collision-strategy rename-type then renames the wrapper apart from the inner model in their module, because a field is named like it, the later holders keep the wrapper and warn, as in 0.86.0. With --collapse-shared-parent-wrappers every holder references the inner model, as the first holder does, and the wrapper leaves the output. The option has no effect without the parent strategy.

Usage

datamodel-codegen --input later_holder_renames_wrapper.yaml --collapse-root-models --collapse-root-models-name-strategy parent --field-type-collision-strategy rename-type --collapse-shared-parent-wrappers # (1)!
  1. --collapse-shared-parent-wrappers - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info:
  title: collapse root models
  version: "1"
paths: {}
components:
  schemas:
    Inner:
      type: object
      properties:
        x:
          type: string
    Wrapper:
      $ref: '#/components/schemas/Inner'
    User:
      type: object
      properties:
        first:
          $ref: '#/components/schemas/Wrapper'
        Wrapper:
          $ref: '#/components/schemas/Wrapper'

Output:

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

from __future__ import annotations

from pydantic import BaseModel


class Wrapper_1(BaseModel):
    x: str | None = None


class User(BaseModel):
    first: Wrapper_1 | None = None
    Wrapper: Wrapper_1 | None = None
# generated by datamodel-codegen:
#   filename:  later_holder_renames_wrapper.yaml

from __future__ import annotations

from pydantic import BaseModel, RootModel


class Wrapper_2(BaseModel):
    x: str | None = None


class Wrapper_1(RootModel[Wrapper_2]):
    root: Wrapper_2


class User(BaseModel):
    first: Wrapper_2 | None = None
    Wrapper: Wrapper_1 | None = None

--dataclass-arguments

Customize dataclass decorator arguments via JSON dictionary.

The --dataclass-arguments flag accepts custom dataclass arguments as a JSON dictionary (e.g., '{"frozen": true, "kw_only": true, "slots": true, "order": true}'). This overrides individual flags like --frozen-dataclasses and provides fine-grained control over dataclass generation.

Related: --frozen-dataclasses, --keyword-only

See also: Output Model Types

Usage

datamodel-codegen --input simple-star-wars.graphql --output-model-type dataclasses.dataclass --dataclass-arguments '{"slots": true, "order": true}' # (1)!
  1. --dataclass-arguments - 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 dataclasses import dataclass
from typing import Literal, TypeAlias

Boolean: TypeAlias = bool
"""
The `Boolean` scalar type represents `true` or `false`.
"""


ID: TypeAlias = 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: TypeAlias = int
"""
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
"""


String: TypeAlias = 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.
"""


@dataclass(order=True, slots=True)
class Film:
    characters: list[Person]
    characters_ids: list[ID]
    director: String
    episode_id: Int
    id: ID
    opening_crawl: String
    planets: list[Planet]
    planets_ids: list[ID]
    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]
    producer: String | None = None
    typename__: Literal['Film'] | None = 'Film'


@dataclass(order=True, slots=True)
class Person:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    species: list[Species]
    species_ids: list[ID]
    starships: list[Starship]
    starships_ids: list[ID]
    vehicles: list[Vehicle]
    vehicles_ids: list[ID]
    birth_year: String | None = None
    eye_color: String | None = None
    gender: String | None = None
    hair_color: String | None = None
    height: Int | None = None
    homeworld: Planet | None = None
    homeworld_id: ID | None = None
    mass: Int | None = None
    skin_color: String | None = None
    typename__: Literal['Person'] | None = 'Person'


@dataclass(order=True, slots=True)
class Planet:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    residents: list[Person]
    residents_ids: list[ID]
    climate: String | None = None
    diameter: String | None = None
    gravity: String | None = None
    orbital_period: String | None = None
    population: String | None = None
    rotation_period: String | None = None
    surface_water: String | None = None
    terrain: String | None = None
    typename__: Literal['Planet'] | None = 'Planet'


@dataclass(order=True, slots=True)
class Species:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    people: list[Person]
    people_ids: list[ID]
    average_height: String | None = None
    average_lifespan: String | None = None
    classification: String | None = None
    designation: String | None = None
    eye_colors: String | None = None
    hair_colors: String | None = None
    language: String | None = None
    skin_colors: String | None = None
    typename__: Literal['Species'] | None = 'Species'


@dataclass(order=True, slots=True)
class Starship:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    pilots: list[Person]
    pilots_ids: list[ID]
    MGLT: String | None = None
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    hyperdrive_rating: String | None = None
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    passengers: String | None = None
    starship_class: String | None = None
    typename__: Literal['Starship'] | None = 'Starship'


@dataclass(order=True, slots=True)
class Vehicle:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    pilots: list[Person]
    pilots_ids: list[ID]
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    passengers: String | None = None
    vehicle_class: String | None = None
    typename__: Literal['Vehicle'] | None = 'Vehicle'

--duplicate-name-suffix

Customize suffix for duplicate model names.

The --duplicate-name-suffix flag allows specifying custom suffixes for resolving duplicate names by type. The value is a JSON mapping where keys are type names ('model', 'enum', 'default') and values are suffix strings. For example, {"model": "Schema"} changes Item1 to ItemSchema.

Related: --naming-strategy

Usage

datamodel-codegen --input input.json --duplicate-name-suffix '{"model": "Schema"}' # (1)!
  1. --duplicate-name-suffix - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "Order": {
      "type": "object",
      "properties": {
        "item": {
          "type": "object",
          "properties": {
            "name": {"type": "string"}
          }
        }
      }
    },
    "Cart": {
      "type": "object",
      "properties": {
        "item": {
          "type": "object",
          "properties": {
            "quantity": {"type": "integer"}
          }
        }
      }
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  input.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 Item(BaseModel):
    name: str | None = None


class Order(BaseModel):
    item: Item | None = None


class ItemSchema(BaseModel):
    quantity: int | None = None


class Cart(BaseModel):
    item: ItemSchema | None = None

--enable-faux-immutability

Enable faux immutability in Pydantic models (frozen=True).

The --enable-faux-immutability flag configures the code generation behavior.

Usage

datamodel-codegen --input api.yaml --enable-faux-immutability # (1)!
  1. --enable-faux-immutability - 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 pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel


class Pet(BaseModel):
    model_config = ConfigDict(
        frozen=True,
    )
    id: int
    name: str
    tag: str | None = None


class Pets(RootModel[list[Pet]]):
    model_config = ConfigDict(
        frozen=True,
    )
    root: list[Pet]


class User(BaseModel):
    model_config = ConfigDict(
        frozen=True,
    )
    id: int
    name: str
    tag: str | None = None


class Users(RootModel[list[User]]):
    model_config = ConfigDict(
        frozen=True,
    )
    root: list[User]


class Id(RootModel[str]):
    model_config = ConfigDict(
        frozen=True,
    )
    root: str


class Rules(RootModel[list[str]]):
    model_config = ConfigDict(
        frozen=True,
    )
    root: list[str]


class Error(BaseModel):
    model_config = ConfigDict(
        frozen=True,
    )
    code: int
    message: str


class Api(BaseModel):
    model_config = ConfigDict(
        frozen=True,
    )
    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]]):
    model_config = ConfigDict(
        frozen=True,
    )
    root: list[Api]


class Event(BaseModel):
    model_config = ConfigDict(
        frozen=True,
    )
    name: str | None = None


class Result(BaseModel):
    model_config = ConfigDict(
        frozen=True,
    )
    event: Event | None = None

--force-optional

Force all fields to be Optional regardless of required status.

The --force-optional flag configures the code generation behavior.

Usage

datamodel-codegen --input api.yaml --force-optional # (1)!
  1. --force-optional - 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 pydantic import AnyUrl, BaseModel, Field, RootModel


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


class Pets(RootModel[list[Pet] | None]):
    root: list[Pet] | None = None


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


class Users(RootModel[list[User] | None]):
    root: list[User] | None = None


class Id(RootModel[str | None]):
    root: str | None = None


class Rules(RootModel[list[str] | None]):
    root: list[str] | None = None


class Error(BaseModel):
    code: int | None = None
    message: str | None = None


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] | None]):
    root: list[Api] | None = None


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


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

--frozen-dataclasses

Generate frozen dataclasses with optional keyword-only fields.

The --frozen-dataclasses flag generates dataclass instances that are immutable (frozen=True). Combined with --keyword-only (Python 3.10+), all fields become keyword-only arguments.

Related: --keyword-only, --output-model-type

See also: Output Model Types

Usage

datamodel-codegen --input simple_frozen_test.json --output-model-type dataclasses.dataclass --frozen-dataclasses # (1)!
  1. --frozen-dataclasses - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "User",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer"
    },
    "email": {
      "type": "string",
      "format": "email"
    }
  },
  "required": ["name", "age"]
}

Output:

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

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True)
class User:
    name: str
    age: int
    email: str | None = None

--keep-constrained-root-models-in-every-container

Keep constrained root models named in every container of a holder.

Under --collapse-root-models with --field-constraints, a root model whose root field has constraints, such as an item schema with minLength, stays named beside a list, a dict or a union of its holder, as Field() arguments could not carry its constraints there, but is inlined into a set, a frozen set, a Sequence or a Mapping, where its constraints are lost, so the holder accepts items the schema rejects. With --keep-constrained-root-models-in-every-container it stays named inside any container.

Usage

datamodel-codegen --input collapse_constrained_roots_in_containers.json --collapse-root-models --field-constraints --use-unique-items-as-set --keep-constrained-root-models-in-every-container # (1)!
  1. --keep-constrained-root-models-in-every-container - the option documented here
Examples

Input Schema:

{
  "title": "Holder",
  "type": "object",
  "properties": {
    "names": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "x-python-type": "Sequence[str]"
    },
    "name_list": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      }
    },
    "counts": {
      "type": "object",
      "additionalProperties": {
        "type": "integer",
        "minimum": 0
      },
      "x-python-type": "Mapping[str, int]"
    },
    "fs": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "x-python-type": "frozenset[str]"
    },
    "assignees": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "uniqueItems": true
    }
  }
}

Output:

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

from __future__ import annotations

from collections.abc import Mapping, Sequence

from pydantic import BaseModel, Field, RootModel


class Name(RootModel[str]):
    root: str = Field(..., min_length=1)


class NameListItem(RootModel[str]):
    root: str = Field(..., min_length=1)


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


class F(RootModel[str]):
    __hash__ = object.__hash__
    root: str = Field(..., min_length=1)


class Assignee(RootModel[str]):
    __hash__ = object.__hash__
    root: str = Field(..., min_length=1)


class Holder(BaseModel):
    names: Sequence[Name] | None = None
    name_list: list[NameListItem] | None = None
    counts: Mapping[str, Counts] | None = None
    fs: frozenset[F] | None = None
    assignees: set[Assignee] | None = None
# generated by datamodel-codegen:
#   filename:  collapse_constrained_roots_in_containers.json

from __future__ import annotations

from collections.abc import Mapping, Sequence

from pydantic import BaseModel, Field, RootModel


class NameListItem(RootModel[str]):
    root: str = Field(..., min_length=1)


class Holder(BaseModel):
    names: Sequence[str] | None = None
    name_list: list[NameListItem] | None = None
    counts: Mapping[str, int] | None = None
    fs: frozenset[str] | None = None
    assignees: set[str] | None = None

--keep-defaults-of-inherited-required-fields

Keep under --use-default the default of a property only an inherited schema makes required.

--use-default writes the default of a required field that has one, but a property whose schema gives a default and that only a schema it inherits from (allOf) lists as required was written without it (class Child(Base): a: str), while the same property kept it when the schema listed it as required itself (a: str = 'x'). With this option it keeps the default in both cases, also through a base of its base and an inline allOf member; dataclasses, Pydantic dataclasses and msgspec make the required fields after it keyword-only, as for a property the schema lists itself.

Usage

datamodel-codegen --input use_default_inherited_required.json --use-default --keep-defaults-of-inherited-required-fields # (1)!
  1. --keep-defaults-of-inherited-required-fields - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Model",
  "type": "object",
  "$defs": {
    "Base": {
      "type": "object",
      "properties": {"a": {"type": "string"}, "b": {"type": "string"}},
      "required": ["a", "b"]
    },
    "Child": {
      "allOf": [{"$ref": "#/$defs/Base"}],
      "properties": {"a": {"type": "string", "default": "x"}, "b": {"type": "string"}}
    },
    "Own": {
      "allOf": [{"$ref": "#/$defs/Base"}],
      "properties": {"a": {"type": "string", "default": "x"}, "b": {"type": "string"}},
      "required": ["a"]
    },
    "Middle": {"allOf": [{"$ref": "#/$defs/Base"}]},
    "Grandchild": {
      "allOf": [{"$ref": "#/$defs/Middle"}],
      "properties": {"a": {"type": "string", "default": "y"}}
    },
    "InlineMember": {
      "allOf": [{"$ref": "#/$defs/Base"}, {"properties": {"a": {"type": "string", "default": "z"}}}]
    }
  },
  "properties": {
    "child": {"$ref": "#/$defs/Child"},
    "own": {"$ref": "#/$defs/Own"},
    "grandchild": {"$ref": "#/$defs/Grandchild"},
    "inline_member": {"$ref": "#/$defs/InlineMember"}
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel


class Base(BaseModel):
    a: str
    b: str


class Child(Base):
    a: str = 'x'
    b: str


class Own(Base):
    a: str = 'x'
    b: str


class Middle(Base):
    pass


class Grandchild(Middle):
    a: str = 'y'


class InlineMember(Base):
    a: str = 'z'


class Model(BaseModel):
    child: Child | None = None
    own: Own | None = None
    grandchild: Grandchild | None = None
    inline_member: InlineMember | None = None
# generated by datamodel-codegen:
#   filename:  use_default_inherited_required.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel


class Base(BaseModel):
    a: str
    b: str


class Child(Base):
    a: str
    b: str


class Own(Base):
    a: str = 'x'
    b: str


class Middle(Base):
    pass


class Grandchild(Middle):
    a: str


class InlineMember(Base):
    a: str


class Model(BaseModel):
    child: Child | None = None
    own: Own | None = None
    grandchild: Grandchild | None = None
    inline_member: InlineMember | None = None

--keep-enum-literal-aliases

Keep a named enum written as a Literal type alias named under collapse.

An output that writes an enum definition as a Literal type alias (TypedDict, or --enum-field-as-literal all) names it at its uses (Status = Literal['open', 'resolved'], status: Status), but --collapse-root-models inlines it, so every use repeats the Literal and the name of the enum is lost. With --keep-enum-literal-aliases the alias stays named; a type alias holds the values of its type, so its uses parse the same values. A Pydantic RootModel class of the Literal still collapses.

Usage

datamodel-codegen --input collapse_enum_literal_aliases.json --output-model-type typing.TypedDict --collapse-root-models --keep-enum-literal-aliases # (1)!
  1. --keep-enum-literal-aliases - the option documented here
Examples

Input Schema:

{
  "title": "Ticket",
  "type": "object",
  "required": [
    "status",
    "history"
  ],
  "properties": {
    "status": {
      "$ref": "#/$defs/Status"
    },
    "history": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Status"
      }
    },
    "name": {
      "$ref": "#/$defs/Name"
    }
  },
  "$defs": {
    "Status": {
      "type": "string",
      "enum": [
        "open",
        "resolved"
      ]
    },
    "Name": {
      "type": "string"
    }
  }
}

Output:

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

from __future__ import annotations

from typing import Literal, TypeAlias, TypedDict

from typing_extensions import NotRequired

Status: TypeAlias = Literal['open', 'resolved']


class Ticket(TypedDict):
    status: Status
    history: list[Status]
    name: NotRequired[str]
# generated by datamodel-codegen:
#   filename:  collapse_enum_literal_aliases.json

from __future__ import annotations

from typing import Literal, TypedDict

from typing_extensions import NotRequired


class Ticket(TypedDict):
    status: Literal['open', 'resolved']
    history: list[Literal['open', 'resolved']]
    name: NotRequired[str]

--keep-false-dataclass-arguments

Write every dataclass decorator argument set to false.

Without this option an argument of --dataclass-arguments set to false is left out of the decorator, so it takes its default: {"eq": false, "frozen": true} writes @dataclass(frozen=True), which compares by value and hashes the values of its fields (eq=True is the default). With it the decorator writes @dataclass(eq=False, frozen=True), so the dataclass compares by identity as asked. Every decision that reads the decorator reads what it writes: a set of such dataclasses under --use-unique-items-as-set-by-value is a list with the option, as they hash by identity. The generation stops on arguments the decorator refuses when the module is imported, such as eq=False beside order=True, weakref_slot without slots=True or for Python 3.10, and match_args, weakref_slot or init=True for a Pydantic dataclass.

Usage

datamodel-codegen --input keep_false_dataclass_arguments.json --output-model-type dataclasses.dataclass --dataclass-arguments '{"eq": false, "frozen": true}' --keep-false-dataclass-arguments # (1)!
  1. --keep-false-dataclass-arguments - the option documented here
Examples

Input Schema:

{
  "title": "Basket",
  "type": "object",
  "properties": {
    "items": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/Item"}}
  },
  "required": ["items"],
  "$defs": {
    "Item": {"type": "object", "properties": {"x": {"type": "integer"}}, "required": ["x"]}
  }
}

Output:

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

from __future__ import annotations

from dataclasses import dataclass


@dataclass(eq=False, frozen=True)
class Item:
    x: int


@dataclass(eq=False, frozen=True)
class Basket:
    items: list[Item]
# generated by datamodel-codegen:
#   filename:  keep_false_dataclass_arguments.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True)
class Item:
    x: int


@dataclass(frozen=True)
class Basket:
    items: set[Item]

--keep-field-defaults-off-branch-roots

Leave a property's default off the root models extracted from its anyOf or oneOf branches.

Under --field-constraints or --use-annotated a branch with constraints, such as {type: number, minimum: 0} in the anyOf of a property with default: null, becomes a root model of its own. Without the option that root takes the property's default, as in 0.86.0: root: float = Field(None, ge=0.0), so the model builds without a value and holds a default its type rejects. With --keep-field-defaults-off-branch-roots the default stays with the property, and the root requires its value: root: float = Field(..., ge=0.0).

Usage

datamodel-codegen --input extracted_branch_default.yaml --field-constraints --keep-field-defaults-off-branch-roots # (1)!
  1. --keep-field-defaults-off-branch-roots - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info:
  title: Extracted branch default
  version: "1"
paths: {}
components:
  schemas:
    Model:
      type: object
      properties:
        weight:
          anyOf:
            - type: number
              minimum: 0
            - type: "null"
          default: null
        quantity:
          anyOf:
            - type: integer
              minimum: 0
            - type: string
              maxLength: 3
          default: 5
        tags:
          anyOf:
            - type: array
              items:
                type: string
              minItems: 1
            - type: "null"
          default: null
        step:
          anyOf:
            - type: number
              minimum: 0
              default: 1
            - type: "null"
          default: null

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class Weight(RootModel[float]):
    root: float = Field(..., ge=0.0)


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


class Quantity1(RootModel[str]):
    root: str = Field(..., max_length=3)


class Tags(RootModel[list[str]]):
    root: list[str] = Field(..., min_length=1)


class Step(RootModel[float]):
    root: float = Field(1, ge=0.0)


class Model(BaseModel):
    weight: Weight | None = None
    quantity: Quantity | Quantity1 | None = Field(5, validate_default=True)
    tags: Tags | None = None
    step: Step | None = None
# generated by datamodel-codegen:
#   filename:  extracted_branch_default.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class Weight(RootModel[float]):
    root: float = Field(None, ge=0.0)


class Quantity(RootModel[int]):
    root: int = Field(5, ge=0)


class Quantity1(RootModel[str]):
    root: str = Field(5, max_length=3)


class Tags(RootModel[list[str]]):
    root: list[str] = Field(None, min_length=1)


class Step(RootModel[float]):
    root: float = Field(1, ge=0.0)


class Model(BaseModel):
    weight: Weight | None = None
    quantity: Quantity | Quantity1 | None = Field(5, validate_default=True)
    tags: Tags | None = None
    step: Step | None = None

--keep-model-order

Keep generated model order deterministic while respecting dependency constraints.

The --keep-model-order flag produces a stable, deterministic output order. The generator starts from class-name order and only moves models when required to satisfy dependency or runtime constraints (for example, a base class must appear before its subclass, and cyclic groups must stay together).

This option is not equivalent to preserving the raw definition order from the input schema, and it does not guarantee a strict unconditional alphabetical order either. Inheritance and other runtime ordering requirements can force a non-alphabetical arrangement. The value of the flag is that repeated runs on the same schema produce the same ordering, which keeps diffs stable.

Related: --collapse-root-models

Usage

datamodel-codegen --input inheritance_forward_ref.json --keep-model-order # (1)!
  1. --keep-model-order - the option documented here
Examples

Input Schema:

{
    "title": "PersonsBestFriend",
    "description": "This is the main model.",
    "type": "object",
    "properties": {
      "people": {
        "title": "People",
        "type": "array",
        "items": {
          "$ref": "#/definitions/Person"
        }
      },
      "dogs": {
        "title": "Dogs",
        "type": "array",
        "items": {
          "$ref": "#/definitions/Dog"
        }
      },
      "dog_base": {
        "$ref": "#/definitions/DogBase"
      },
      "dog_relationships": {
        "$ref": "#/definitions/DogRelationships"
      },
      "person_base": {
        "$ref": "#/definitions/PersonBase"
      },
      "person_relationships": {
        "$ref": "#/definitions/PersonRelationships"
      }
    },
    "definitions": {
      "Person": {
        "title": "Person",
        "allOf": [
            {"$ref": "#/definitions/PersonBase"},
            {"$ref": "#/definitions/PersonRelationships"}
        ]
      },
      "Dog": {
        "title": "Dog",
        "allOf": [
            {"$ref": "#/definitions/DogBase"},
            {"$ref": "#/definitions/DogRelationships"}
        ]
      },
      "DogBase": {
        "title": "DogBase",
        "type": "object",
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          },
          "woof": {
            "title": "Woof",
            "default": true,
            "type": "boolean"
          }
        }
      },
      "DogRelationships": {
        "title": "DogRelationships",
        "type": "object",
        "properties": {
          "people": {
            "title": "People",
            "type": "array",
            "items": {
              "$ref": "#/definitions/Person"
            }
          }
        }
      },
      "PersonBase": {
        "title": "PersonBase",
        "type": "object",
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          }
        }
      },
      "PersonRelationships": {
        "title": "PersonRelationships",
        "type": "object",
        "properties": {
          "people": {
            "title": "People",
            "type": "array",
            "items": {
              "$ref": "#/definitions/Person"
            }
          }
        }
      }
    }
  }

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field


class DogBase(BaseModel):
    name: str | None = Field(None, title='Name')
    woof: bool | None = Field(True, title='Woof')


class DogRelationships(BaseModel):
    people: list[Person] | None = Field(None, title='People')


class Dog(DogBase, DogRelationships):
    pass


class PersonBase(BaseModel):
    name: str | None = Field(None, title='Name')


class PersonRelationships(BaseModel):
    people: list[Person] | None = Field(None, title='People')


class Person(PersonBase, PersonRelationships):
    pass


class PersonsBestFriend(BaseModel):
    people: list[Person] | None = Field(None, title='People')
    dogs: list[Dog] | None = Field(None, title='Dogs')
    dog_base: DogBase | None = None
    dog_relationships: DogRelationships | None = None
    person_base: PersonBase | None = None
    person_relationships: PersonRelationships | None = None


DogRelationships.model_rebuild()
Dog.model_rebuild()
PersonRelationships.model_rebuild()
Person.model_rebuild()

--keep-reference-null-on-collapsed-root-models

Keep the null of a root model that admits null where --collapse-root-models inlines it.

An OpenAPI 3.0 schema with nullable: true beside its type admits null, and its root model writes it (RootModel[list[str] | None], Names: TypeAlias = list[str] | None), but where --collapse-root-models inlines that root model into a field, an array item or a map value, the inlined type is the root's type without the null, so the field rejects the null the root model accepts. With this option the inlined type keeps it (names: list[str] | None), also where a name strategy gives the field the model a nullable root names.

Usage

datamodel-codegen --input collapse_nullable_roots.yaml --collapse-root-models --keep-reference-null-on-collapsed-root-models # (1)!
  1. --keep-reference-null-on-collapsed-root-models - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info:
  title: collapse nullable roots
  version: "1"
paths: {}
components:
  schemas:
    Names:
      type: array
      items:
        type: string
      nullable: true
    NamesAlias:
      $ref: '#/components/schemas/Names'
    Label:
      type: string
      nullable: true
    Pet:
      type: object
      properties:
        n:
          type: string
    NullablePet:
      $ref: '#/components/schemas/Pet'
      nullable: true
    Holder:
      type: object
      required:
        - names
        - label
      properties:
        names:
          $ref: '#/components/schemas/Names'
        label:
          $ref: '#/components/schemas/Label'
        alias:
          $ref: '#/components/schemas/NamesAlias'
        listed:
          type: array
          items:
            $ref: '#/components/schemas/Names'
        mapped:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Names'
        first:
          $ref: '#/components/schemas/NullablePet'
        second:
          $ref: '#/components/schemas/NullablePet'

Output:

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

from __future__ import annotations

from pydantic import BaseModel, RootModel


class Pet(BaseModel):
    n: str | None = None


class NullablePet(RootModel[Pet | None]):
    root: Pet | None = None


class Holder(BaseModel):
    names: list[str] | None
    label: str | None
    alias: list[str] | None = None
    listed: list[list[str] | None] | None = None
    mapped: dict[str, list[str] | None] | None = None
    first: NullablePet | None = None
    second: NullablePet | None = None
# generated by datamodel-codegen:
#   filename:  collapse_nullable_roots.yaml

from __future__ import annotations

from pydantic import BaseModel, RootModel


class Pet(BaseModel):
    n: str | None = None


class NullablePet(RootModel[Pet | None]):
    root: Pet | None = None


class Holder(BaseModel):
    names: list[str]
    label: str
    alias: list[str] | None = None
    listed: list[list[str]] | None = None
    mapped: dict[str, list[str]] | None = None
    first: NullablePet | None = None
    second: NullablePet | None = None

--keep-reference-null-on-merged-models

Keep the null a reference's schema admits when its model is merged.

Deduplication of equal models, --reuse-model, --collapse-reuse-models and --reuse-scope tree merge a model into an equal one, and point the fields, items and members that named it at the model that stays. Without the option such a reference takes the null of the model it names after the merge, so a type: [object, null] property whose model is merged into an equal model that rejects null loses its | None and rejects the null its schema admits. With --keep-reference-null-on-merged-models it keeps the null of the schema it names, so a model that differs from another only by that null stays apart under --reuse-model. A reference whose schema rejects null keeps rejecting it in both cases.

Usage

datamodel-codegen --input keep_reference_null_on_merged_models.json --strict-nullable --reuse-model --keep-reference-null-on-merged-models # (1)!
  1. --keep-reference-null-on-merged-models - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Holder",
  "type": "object",
  "required": ["first", "second", "home", "work"],
  "properties": {
    "first": {"type": "object", "properties": {"tool": {"type": "object", "properties": {"name": {"type": "string"}}}}},
    "second": {
      "type": "object",
      "required": ["tool"],
      "properties": {"tool": {"type": ["object", "null"], "properties": {"name": {"type": "string"}}}}
    },
    "bar": {"$ref": "#/$defs/Bar"},
    "foo": {"$ref": "#/$defs/Foo"},
    "home": {"$ref": "#/$defs/Home"},
    "homes": {"type": "array", "items": {"$ref": "#/$defs/Home"}},
    "work": {"$ref": "#/$defs/Work"}
  },
  "$defs": {
    "Bar": {"type": "object", "properties": {"item": {"type": "object", "properties": {"count": {"type": "integer"}}}}},
    "Foo": {
      "type": "object",
      "properties": {"item": {"type": ["object", "null"], "properties": {"count": {"type": "integer"}}}}
    },
    "Work": {"type": "object", "properties": {"street": {"type": "string"}}},
    "Home": {"type": ["object", "null"], "properties": {"street": {"type": "string"}}}
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel


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


class First(BaseModel):
    tool: Tool | None = None


class Second(BaseModel):
    tool: Tool | None


class Item(BaseModel):
    count: int | None = None


class Bar(BaseModel):
    item: Item | None = None


class Foo(Bar):
    pass


class Work(BaseModel):
    street: str | None = None


class Home(Work):
    pass


class Holder(BaseModel):
    first: First
    second: Second
    bar: Bar | None = None
    foo: Foo | None = None
    home: Home | None
    homes: list[Home | None] | None = None
    work: Work
# generated by datamodel-codegen:
#   filename:  keep_reference_null_on_merged_models.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel


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


class First(BaseModel):
    tool: Tool | None = None


class Second(BaseModel):
    tool: Tool


class Item(BaseModel):
    count: int | None = None


class Bar(BaseModel):
    item: Item | None = None


class Foo(Bar):
    pass


class Work(BaseModel):
    street: str | None = None


class Home(Work):
    pass


class Holder(BaseModel):
    first: First
    second: Second
    bar: Bar | None = None
    foo: Foo | None = None
    home: Home
    homes: list[Home | None] | None = None
    work: Work

--keep-self-referencing-array-items

Keep the items of an array whose items name the array itself.

An array schema whose items name it, such as Node = array of (Node | Leaf) or Chain = array of Chain, is written as a bare list (class Node(RootModel[list])), which accepts any item. With this option it keeps its items (RootModel[list[Union["Node", Leaf]]]), so an item the schema rejects is rejected. A type list that lists the array beside other types (type: [array, string]) is written as before. msgspec output keeps the bare list: msgspec cannot decode a type alias that names itself through no Struct.

Usage

datamodel-codegen --input self_referencing_array_items.json --keep-self-referencing-array-items # (1)!
  1. --keep-self-referencing-array-items - the option documented here
Examples

Input Schema:

{
  "title": "Root",
  "type": "object",
  "properties": {
    "tree": {"$ref": "#/$defs/Node"},
    "chain": {"$ref": "#/$defs/Chain"}
  },
  "$defs": {
    "Node": {"type": "array", "items": {"anyOf": [{"$ref": "#/$defs/Node"}, {"$ref": "#/$defs/Leaf"}]}},
    "Leaf": {"type": "string"},
    "Chain": {"type": "array", "items": {"$ref": "#/$defs/Chain"}}
  }
}

Output:

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

from __future__ import annotations

from typing import Union

from pydantic import BaseModel, RootModel


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


class Chain(RootModel[list["Chain"]]):
    root: list["Chain"]


class Node(RootModel[list[Union["Node", Leaf]]]):
    root: list[Union["Node", Leaf]]


class Root(BaseModel):
    tree: Node | None = None
    chain: Chain | None = None


Chain.model_rebuild()
Node.model_rebuild()
# generated by datamodel-codegen:
#   filename:  self_referencing_array_items.json

from __future__ import annotations

from pydantic import BaseModel, RootModel


class Node(RootModel[list]):
    root: list


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


class Chain(RootModel[list]):
    root: list


class Root(BaseModel):
    tree: Node | None = None
    chain: Chain | None = None

--keep-shared-members-on-collapsed-root-models

Keep each member of a root type that collapse inlined at several sites at every one of them.

--collapse-root-models writes the root type of a root model at each site that names it, and those copies share their members. When a member names another root model that collapse inlines only afterwards, as the plain member of a recursive union is reached through the recursion, earlier releases put its type into one copy alone and left the other copies with a member that writes nothing: values: dict[str, "Entry"] drops the str of Fallback, so a value the schema accepts is rejected, and a copy that has no member left writes Any. With this option every copy takes the member's type (values: dict[str, Union["Entry", str]]); a copy that lies inside that type keeps naming the member's model, so no type contains itself.

Usage

datamodel-codegen --input collapse_shared_members.json --collapse-root-models --keep-shared-members-on-collapsed-root-models # (1)!
  1. --keep-shared-members-on-collapsed-root-models - the option documented here
Examples

Input Schema:

{
  "type": "object",
  "definitions": {
    "Obj": {"type": "object", "patternProperties": {"^t@.+$": {"$ref": "#/definitions/Either"}}},
    "Entry": {"anyOf": [{"$ref": "#/definitions/Obj"}]},
    "Fallback": {"type": "string"},
    "Either": {"anyOf": [{"$ref": "#/definitions/Entry"}, {"$ref": "#/definitions/Fallback"}]}
  },
  "properties": {
    "values": {"type": "object", "additionalProperties": {"$ref": "#/definitions/Either"}}
  }
}

Output:

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

from __future__ import annotations

from typing import Union

from pydantic import BaseModel, RootModel, constr


class Model(BaseModel):
    values: dict[str, Union["Entry", str]] | None = None


class Entry(RootModel[dict[constr(pattern=r'^t@.+$'), Union["Entry", str]]]):
    root: dict[constr(pattern=r'^t@.+$'), Union["Entry", str]]


Model.model_rebuild()
Entry.model_rebuild()
# generated by datamodel-codegen:
#   filename:  collapse_shared_members.json

from __future__ import annotations

from typing import Union

from pydantic import BaseModel, RootModel, constr


class Model(BaseModel):
    values: dict[str, "Entry"] | None = None


class Entry(RootModel[dict[constr(pattern=r'^t@.+$'), Union["Entry", str]]]):
    root: dict[constr(pattern=r'^t@.+$'), Union["Entry", str]]


Model.model_rebuild()
Entry.model_rebuild()

--keyword-only

Generate dataclasses with keyword-only fields (Python 3.10+).

The --keyword-only flag generates dataclasses where all fields must be specified as keyword arguments (kw_only=True). This is only available for Python 3.10+. When combined with --frozen-dataclasses, it creates immutable dataclasses with keyword-only arguments, improving code clarity and preventing positional argument errors.

Related: --frozen-dataclasses, --output-model-type, --target-python-version

See also: Output Model Types

Option relationships:

  • Requires: --target-python-version = 3.10+ - --keyword-only requires --target-python-version 3.10 or higher for dataclasses.

Usage

datamodel-codegen --input simple-star-wars.graphql --output-model-type dataclasses.dataclass --frozen-dataclasses --keyword-only --target-python-version 3.10 # (1)!
  1. --keyword-only - 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 dataclasses import dataclass
from typing import Any


@dataclass(frozen=True, kw_only=True)
class Person:
    firstName: str | None = None
    lastName: str | None = None
    age: int | None = None
    friends: list[Any] | None = None
    comment: None = None

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 dataclasses import dataclass
from typing import Literal, TypeAlias

Boolean: TypeAlias = bool
"""
The `Boolean` scalar type represents `true` or `false`.
"""


ID: TypeAlias = 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: TypeAlias = int
"""
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
"""


String: TypeAlias = 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.
"""


@dataclass(frozen=True, kw_only=True)
class Film:
    characters: list[Person]
    characters_ids: list[ID]
    director: String
    episode_id: Int
    id: ID
    opening_crawl: String
    planets: list[Planet]
    planets_ids: list[ID]
    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]
    producer: String | None = None
    typename__: Literal['Film'] | None = 'Film'


@dataclass(frozen=True, kw_only=True)
class Person:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    species: list[Species]
    species_ids: list[ID]
    starships: list[Starship]
    starships_ids: list[ID]
    vehicles: list[Vehicle]
    vehicles_ids: list[ID]
    birth_year: String | None = None
    eye_color: String | None = None
    gender: String | None = None
    hair_color: String | None = None
    height: Int | None = None
    homeworld: Planet | None = None
    homeworld_id: ID | None = None
    mass: Int | None = None
    skin_color: String | None = None
    typename__: Literal['Person'] | None = 'Person'


@dataclass(frozen=True, kw_only=True)
class Planet:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    residents: list[Person]
    residents_ids: list[ID]
    climate: String | None = None
    diameter: String | None = None
    gravity: String | None = None
    orbital_period: String | None = None
    population: String | None = None
    rotation_period: String | None = None
    surface_water: String | None = None
    terrain: String | None = None
    typename__: Literal['Planet'] | None = 'Planet'


@dataclass(frozen=True, kw_only=True)
class Species:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    people: list[Person]
    people_ids: list[ID]
    average_height: String | None = None
    average_lifespan: String | None = None
    classification: String | None = None
    designation: String | None = None
    eye_colors: String | None = None
    hair_colors: String | None = None
    language: String | None = None
    skin_colors: String | None = None
    typename__: Literal['Species'] | None = 'Species'


@dataclass(frozen=True, kw_only=True)
class Starship:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    pilots: list[Person]
    pilots_ids: list[ID]
    MGLT: String | None = None
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    hyperdrive_rating: String | None = None
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    passengers: String | None = None
    starship_class: String | None = None
    typename__: Literal['Starship'] | None = 'Starship'


@dataclass(frozen=True, kw_only=True)
class Vehicle:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    pilots: list[Person]
    pilots_ids: list[ID]
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    passengers: String | None = None
    vehicle_class: String | None = None
    typename__: Literal['Vehicle'] | None = 'Vehicle'

--merge-message-trait-headers

Give an AsyncAPI message the headers of all its traits, merged in order, and then its own.

AsyncAPI 2 and 3 apply the traits of a message in the order they are listed, each as a JSON Merge Patch, and the message's own fields win over them. Without the option a message's headers are its own, else those of its one trait that is no $ref and defines them, else those of a referenced trait; the headers of the other traits are left out, and a second inline trait with headers is an error. With --merge-message-trait-headers the headers of every trait, inline or $ref, are merged in order and then the message's own: a property a later trait or the message gives replaces the earlier one, a $ref is read as the schema it names, and a property set to null is removed. A message whose headers come from one place keeps the model it has without the option.

Usage

datamodel-codegen --input v3.yaml --merge-message-trait-headers # (1)!
  1. --merge-message-trait-headers - the option documented here
Examples

Input Schema:

asyncapi: 3.0.0
info:
  title: Message trait headers merged in order
  version: 1.0.0
channels:
  c:
    address: c
    messages:
      inlineFirst:
        payload:
          type: string
        traits:
          - headers:
              type: object
              properties:
                a:
                  type: string
          - $ref: '#/components/messageTraits/H'
      refFirst:
        payload:
          type: string
        traits:
          - $ref: '#/components/messageTraits/H'
          - headers:
              type: object
              required:
                - b
              properties:
                b:
                  type: string
                  maxLength: 8
      ownHeaders:
        payload:
          type: string
        headers:
          type: object
          required:
            - id
          properties:
            id:
              type: integer
            b:
              type: boolean
        traits:
          - $ref: '#/components/messageTraits/H'
          - headers:
              $ref: '#/components/schemas/Trace'
      onlyRef:
        payload:
          type: string
        traits:
          - $ref: '#/components/messageTraits/H'
components:
  schemas:
    Trace:
      type: object
      properties:
        traceId:
          type: string
          format: uuid
  messageTraits:
    H:
      headers:
        type: object
        properties:
          b:
            type: integer

Output:

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

from __future__ import annotations

from uuid import UUID

from pydantic import BaseModel, RootModel, constr


class Trace(BaseModel):
    traceId: UUID | None = None


class HHeaders(BaseModel):
    b: int | None = None


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


class CInlineFirstHeaders(BaseModel):
    a: str | None = None
    b: int | None = None


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


class CRefFirstHeaders(BaseModel):
    b: constr(max_length=8)


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


class COwnHeadersHeaders(BaseModel):
    b: bool | None = None
    traceId: UUID | None = None
    id: int


class COnlyRefPayload(RootModel[str]):
    root: str
# generated by datamodel-codegen:
#   filename:  v3.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from uuid import UUID

from pydantic import BaseModel, RootModel, constr


class Trace(BaseModel):
    traceId: UUID | None = None


class HHeaders(BaseModel):
    b: int | None = None


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


class CInlineFirstHeaders(BaseModel):
    a: str | None = None


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


class CRefFirstHeaders(BaseModel):
    b: constr(max_length=8)


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


class COwnHeadersHeaders(BaseModel):
    id: int
    b: bool | None = None


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

--model-extra-keys

Add model-level schema extensions to ConfigDict json_schema_extra.

The --model-extra-keys flag adds specified x-* extensions from the schema to the model's ConfigDict json_schema_extra.

Usage

datamodel-codegen --input model_extras.json --model-extra-keys x-custom-metadata # (1)!
  1. --model-extra-keys - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "ModelExtras",
  "type": "object",
  "x-custom-metadata": {"key1": "value1"},
  "x-version": 1,
  "properties": {
    "name": {"type": "string"}
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, ConfigDict


class ModelExtras(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={'x-custom-metadata': {'key1': 'value1'}},
    )
    name: str | None = None

--model-extra-keys-without-x-prefix

Strip x- prefix from model-level schema extensions and add to ConfigDict json_schema_extra.

The --model-extra-keys-without-x-prefix flag adds specified x-* extensions from the schema to the model's ConfigDict json_schema_extra with the x- prefix stripped.

Usage

datamodel-codegen --input model_extras.json --model-extra-keys-without-x-prefix x-custom-metadata x-version # (1)!
  1. --model-extra-keys-without-x-prefix - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "ModelExtras",
  "type": "object",
  "x-custom-metadata": {"key1": "value1"},
  "x-version": 1,
  "properties": {
    "name": {"type": "string"}
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, ConfigDict


class ModelExtras(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={'custom-metadata': {'key1': 'value1'}, 'version': 1},
    )
    name: str | None = None

--model-name-map

Rename generated model classes from a JSON mapping.

The --model-name-map option applies explicit class names to generated models. Mapping keys can be canonical schema refs such as #/definitions/Foo or the class name a model has in the output without the map, such as Foo1; the other models keep the names they have there. Values are final Python class names.

This is useful when a schema cannot be edited but generated model names must be stable for public APIs or downstream code. Colliding mapped names fail instead of being silently suffixed. Keys that match no model, such as a misspelled key, are reported in a warning. GraphQL input does not apply --model-name-map, so every key is reported there.

Related: --naming-strategy, --use-title-as-name

Usage

datamodel-codegen --input model_name_map.json --model-name-map '{"#/definitions/Foo": "RenamedFoo", "Bar": "RenamedBar", "model-name": "OriginalMapped"}' # (1)!
  1. --model-name-map - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "item": {
      "$ref": "#/definitions/Foo"
    },
    "related": {
      "$ref": "#/definitions/Bar"
    },
    "original": {
      "$ref": "#/definitions/model-name"
    }
  },
  "definitions": {
    "Foo": {
      "type": "object",
      "properties": {
        "value": {
          "type": "string"
        }
      }
    },
    "Bar": {
      "type": "object",
      "properties": {
        "foo": {
          "$ref": "#/definitions/Foo"
        }
      }
    },
    "model-name": {
      "type": "object",
      "properties": {
        "bar": {
          "$ref": "#/definitions/Bar"
        }
      }
    }
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel


class RenamedFoo(BaseModel):
    value: str | None = None


class RenamedBar(BaseModel):
    foo: RenamedFoo | None = None


class OriginalMapped(BaseModel):
    bar: RenamedBar | None = None


class Model(BaseModel):
    item: RenamedFoo | None = None
    related: RenamedBar | None = None
    original: OriginalMapped | None = None

--name-converted-payloads-by-message

Name a converted payload that names no type of its own after its message.

An AsyncAPI payload in Avro or XML Schema is converted to JSON Schema first. A payload that names no type of its own, such as an Avro string, array, map or union, or an XML Schema with several global elements, takes the converter's placeholder title Model: the root of a string, array or union payload writes Field(..., title='Model'), and under --use-title-as-name a string, array, map or XML Schema payload is named Model, Model1, .... With --name-converted-payloads-by-message such a payload takes no title, as a JSON Schema payload, so its class is named after its message (PingPublishPayload) under --use-title-as-name too. A payload that names its type, such as an Avro record, keeps that name.

Related: --use-title-as-name

Usage

datamodel-codegen --input converted_payload_names.yaml --name-converted-payloads-by-message # (1)!
  1. --name-converted-payloads-by-message - the option documented here
Examples

Input Schema:

asyncapi: 2.6.0
info: {title: t, version: '1'}
channels:
  text:
    publish:
      message:
        name: Text
        schemaFormat: application/vnd.apache.avro;version=1.9.0
        payload: string
  ping:
    publish:
      message:
        name: Ping
        schemaFormat: application/vnd.apache.avro;version=1.9.0
        payload: {type: array, items: string}
  pong:
    publish:
      message:
        name: Pong
        schemaFormat: application/vnd.apache.avro;version=1.9.0
        payload: {type: map, values: int}
  rec:
    publish:
      message:
        name: Rec
        schemaFormat: application/vnd.apache.avro;version=1.9.0
        payload: {type: record, name: Model, fields: [{name: a, type: string}]}
  uni:
    publish:
      message:
        name: Uni
        schemaFormat: application/vnd.apache.avro;version=1.9.0
        payload: ["null", "string"]
  xml:
    publish:
      message:
        name: Xml
        schemaFormat: application/xml;version=1.0
        payload: |
          <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:element name="A" type="xs:string"/>
            <xs:element name="B" type="xs:int"/>
          </xs:schema>

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel, conint


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


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


class PongPublishPayload(RootModel[dict[str, int]]):
    root: dict[str, int]


class RecPublishPayload(BaseModel):
    a: str


class UniPublishPayload(RootModel[str | None]):
    root: str | None


class XmlPublishPayload(BaseModel):
    A: str = Field(..., title='A')
    B: conint(ge=-2147483648, le=2147483647) = Field(..., title='B')
# generated by datamodel-codegen:
#   filename:  converted_payload_names.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel, conint


class TextPublishPayload(RootModel[str]):
    root: str = Field(..., title='Model')


class PingPublishPayload(RootModel[list[str]]):
    root: list[str] = Field(..., title='Model')


class PongPublishPayload(RootModel[dict[str, int]]):
    root: dict[str, int]


class RecPublishPayload(BaseModel):
    a: str


class UniPublishPayload(RootModel[str | None]):
    root: str | None = Field(..., title='Model')


class XmlPublishPayload(BaseModel):
    A: str = Field(..., title='A')
    B: conint(ge=-2147483648, le=2147483647) = Field(..., title='B')

--naming-strategy

Choose how models are named and how duplicate model names are told apart.

numbered (the default) keeps a model's own name and numbers a duplicate (Item, Item1). parent-prefixed and full-path prefix every nested model with the name of the model that holds it, joined in CamelCase and with nested parents included, also where the name is unique: both give the same model names. For example, Order and Cart with an inline item give OrderItem and CartItem (here ModelOrderItem and ModelCartItem, as the definitions sit below the root model Model), and Company > employee > home_address gives CompanyEmployeeHomeAddress.

primary-first numbers a duplicate as numbered does, but renames a model of another file that holds the name of a primary definition. definitions-first gives every definition (in /definitions/, /$defs/ or /components/schemas/ of any document) its own name before an inline model, a union branch or another definition that asked for it first, which takes the name the definition would have taken (Item1); a model whose name is made from a renamed model, such as the model of its extra properties, is renamed with it. enclosing-model prefixes every nested model with the final name of the model it is built for, once, and a branch of a union without a name of its own with its position (StreamEvent1), while a definition keeps its own name (Customer, not ModelCustomer).

Generated clients and servers (experimental) follow the same rules for their method, argument, module, and class names, with the resource or router group as the parent of a method and the method as the parent of an argument, but prefix only a name their scope already holds: parent-prefixed with its innermost enclosing scope, full-path with every enclosing scope (enclosing-model as full-path); under primary-first and definitions-first, a primary name is one the root document declares.

Related: --duplicate-name-suffix, --parent-scoped-naming, --read-only-write-only-model-type, --use-tag-as-union-variant-name

Usage

datamodel-codegen --input input.json --naming-strategy parent-prefixed # (1)!
  1. --naming-strategy - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info: {title: definitions first, version: "1"}
paths: {}
components:
  schemas:
    build:
      type: object
      properties:
        package:
          type: object
          properties:
            id: {type: string, readOnly: true}
            path: {type: string}
          additionalProperties:
            type: object
            title: PackageExtra
            properties:
              size: {type: integer}
    package:
      type: object
      properties:
        id: {type: string, readOnly: true}
        name: {type: string}
      additionalProperties:
        type: object
        properties:
          weight: {type: integer}
    holder:
      type: object
      properties:
        pkg: {$ref: '#/components/schemas/package'}
    application_fee:
      type: object
      properties:
        charge:
          anyOf:
            - {type: string, maxLength: 5000}
            - $ref: '#/components/schemas/charge'
    charge:
      type: object
      properties:
        id: {type: string}
    event:
      allOf:
        - $ref: '#/components/schemas/holder'
        - oneOf:
            - type: object
              properties:
                created: {type: string}
            - type: object
              properties:
                deleted: {type: string}

Output:

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

from __future__ import annotations

from typing import Dict

from pydantic import BaseModel, ConfigDict, RootModel, constr


class Package1AdditionalProperty(BaseModel):
    size: int | None = None


class Package1(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    __annotations__ = {
        '__pydantic_extra__': Dict[str, Package1AdditionalProperty],
    }
    id: str | None = None
    path: str | None = None


class Build(BaseModel):
    package: Package1 | None = None


class PackageAdditionalProperty(BaseModel):
    weight: int | None = None


class Package(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    __annotations__ = {
        '__pydantic_extra__': Dict[str, PackageAdditionalProperty],
    }
    id: str | None = None
    name: str | None = None


class Holder(BaseModel):
    pkg: Package | None = None


class Charge(BaseModel):
    id: str | None = None


class Event1(BaseModel):
    created: str | None = None


class Event2(BaseModel):
    deleted: str | None = None


class Event3(Holder):
    pass


class Event4(Event1, Event3):
    pass


class Event5(Event2, Event3):
    pass


class Event(RootModel[Event4 | Event5]):
    root: Event4 | Event5


class ApplicationFee(BaseModel):
    charge: constr(max_length=5000) | Charge | None = None
# generated by datamodel-codegen:
#   filename:  definitions_first.yaml

from __future__ import annotations

from typing import Dict

from pydantic import BaseModel, ConfigDict, RootModel, constr


class PackageAdditionalProperty(BaseModel):
    size: int | None = None


class Package(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    __annotations__ = {
        '__pydantic_extra__': Dict[str, PackageAdditionalProperty],
    }
    id: str | None = None
    path: str | None = None


class Build(BaseModel):
    package: Package | None = None


class Package1AdditionalProperty(BaseModel):
    weight: int | None = None


class Package1(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    __annotations__ = {
        '__pydantic_extra__': Dict[str, Package1AdditionalProperty],
    }
    id: str | None = None
    name: str | None = None


class Holder(BaseModel):
    pkg: Package1 | None = None


class Charge(BaseModel):
    id: str | None = None


class Event1(BaseModel):
    created: str | None = None


class Event2(BaseModel):
    deleted: str | None = None


class Event3(Holder):
    pass


class Event4(Event1, Event3):
    pass


class Event5(Event2, Event3):
    pass


class Event(RootModel[Event4 | Event5]):
    root: Event4 | Event5


class ApplicationFee(BaseModel):
    charge: constr(max_length=5000) | Charge | None = None

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "Order": {
      "type": "object",
      "properties": {
        "item": {
          "type": "object",
          "properties": {
            "name": {"type": "string"}
          }
        }
      }
    },
    "Cart": {
      "type": "object",
      "properties": {
        "item": {
          "type": "object",
          "properties": {
            "quantity": {"type": "integer"}
          }
        }
      }
    }
  }
}

Output:

# generated by datamodel-codegen:
#   filename:  input.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 ModelOrderItem(BaseModel):
    name: str | None = None


class ModelOrder(BaseModel):
    item: ModelOrderItem | None = None


class ModelCartItem(BaseModel):
    quantity: int | None = None


class ModelCart(BaseModel):
    item: ModelCartItem | None = None

--omit-incomplete-model-defaults

Write a property whose object default lacks required fields of its model without that default.

A JSON Schema default is an annotation that is not validated, so a schema can give a property an object default that its own model rejects, such as default: {} on a property whose model has required fields (the Kubernetes specs do this throughout). The generated model validates that default (Field({}, validate_default=True), msgspec convert), so valid input that leaves the property out fails. With this option such a property is written without the default (spec: PodSpec | None = None), as if the schema gave none, so that input is valid.

Usage

datamodel-codegen --input incomplete_model_defaults.yaml --omit-incomplete-model-defaults # (1)!
  1. --omit-incomplete-model-defaults - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info: {title: incomplete model defaults, version: "1"}
paths: {}
components:
  schemas:
    PodSpec:
      type: object
      required: [containers]
      properties:
        containers:
          type: array
          items: {type: string}
        hostname:
          type: string
    LabelSelector:
      type: object
      required: [matchLabels]
      properties:
        matchLabels:
          type: object
          additionalProperties: {type: string}
    WorkloadSpec:
      allOf:
        - $ref: '#/components/schemas/LabelSelector'
      properties:
        replicas:
          type: integer
    Labels:
      type: object
      additionalProperties: {type: string}
    PodTemplateSpec:
      type: object
      properties:
        priority:
          type: integer
          default: 0
        labels:
          $ref: '#/components/schemas/Labels'
          default: {}
        annotations:
          type: object
          additionalProperties: {type: string}
          default: {}
        selectorOrName:
          anyOf:
            - $ref: '#/components/schemas/LabelSelector'
            - type: string
          default: {matchLabels: {}}
        spec:
          allOf:
            - $ref: '#/components/schemas/PodSpec'
          default: {}
        nullableSpec:
          anyOf:
            - $ref: '#/components/schemas/PodSpec'
            - type: 'null'
          default: {hostname: a}
        completeSpec:
          allOf:
            - $ref: '#/components/schemas/PodSpec'
          default: {containers: [app]}
        workload:
          allOf:
            - $ref: '#/components/schemas/WorkloadSpec'
          default: {replicas: 1}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class PodSpec(BaseModel):
    containers: list[str]
    hostname: str | None = None


class LabelSelector(BaseModel):
    matchLabels: dict[str, str]


class WorkloadSpec(LabelSelector):
    replicas: int | None = None


class Labels(RootModel[dict[str, str]]):
    root: dict[str, str]


class PodTemplateSpec(BaseModel):
    priority: int | None = 0
    labels: Labels | None = Field({}, validate_default=True)
    annotations: dict[str, str] | None = {}
    selectorOrName: LabelSelector | str | None = Field(
        {'matchLabels': {}}, validate_default=True
    )
    spec: PodSpec | None = None
    nullableSpec: PodSpec | None = None
    completeSpec: PodSpec | None = Field({'containers': ['app']}, validate_default=True)
    workload: WorkloadSpec | None = None
# generated by datamodel-codegen:
#   filename:  incomplete_model_defaults.yaml

from __future__ import annotations

from pydantic import BaseModel, Field, RootModel


class PodSpec(BaseModel):
    containers: list[str]
    hostname: str | None = None


class LabelSelector(BaseModel):
    matchLabels: dict[str, str]


class WorkloadSpec(LabelSelector):
    replicas: int | None = None


class Labels(RootModel[dict[str, str]]):
    root: dict[str, str]


class PodTemplateSpec(BaseModel):
    priority: int | None = 0
    labels: Labels | None = Field({}, validate_default=True)
    annotations: dict[str, str] | None = {}
    selectorOrName: LabelSelector | str | None = Field(
        {'matchLabels': {}}, validate_default=True
    )
    spec: PodSpec | None = Field({}, validate_default=True)
    nullableSpec: PodSpec | None = Field({'hostname': 'a'}, validate_default=True)
    completeSpec: PodSpec | None = Field({'containers': ['app']}, validate_default=True)
    workload: WorkloadSpec | None = Field({'replicas': 1}, validate_default=True)

--omit-redundant-reference-null

Do not write None again at a reference to a model that holds null itself.

When a field, an array item, a map value or a union member references a schema that admits null, the reference writes | None beside the model. A root model whose type admits None, a type alias whose type admits None and an enum with a None member hold that null themselves, so with this option the reference writes the model alone and a null parses to the model (Name(root=None) instead of None). An object model, and an enum without a None member, cannot hold null and keep the | None; so does a None the reference writes itself, such as anyOf: [{$ref}, {type: null}] or an optional field's default.

Usage

datamodel-codegen --input redundant_reference_null.yaml --strict-nullable --omit-redundant-reference-null # (1)!
  1. --omit-redundant-reference-null - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info: {title: Redundant reference null, version: "1"}
paths: {}
components:
  schemas:
    Name: {type: [string, "null"]}
    Color: {enum: [red, null]}
    Size: {type: string, enum: [s, m]}
    Pet: {type: object, properties: {id: {type: integer}}}
    Use:
      type: object
      required: [name_f, name_a, name_m, name_u, name_o, color_f, color_a, color_m, color_u, size_f, size_a, size_m, size_u, pet_f, pet_a, pet_m, pet_u]
      properties:
        name_f: {$ref: '#/components/schemas/Name'}
        name_a: {type: array, items: {$ref: '#/components/schemas/Name'}}
        name_m: {type: object, additionalProperties: {$ref: '#/components/schemas/Name'}}
        name_u: {anyOf: [{$ref: '#/components/schemas/Name'}, {type: integer}]}
        name_o: {anyOf: [{$ref: '#/components/schemas/Name'}, {type: "null"}]}
        name_d: {$ref: '#/components/schemas/Name'}
        color_f: {$ref: '#/components/schemas/Color'}
        color_a: {type: array, items: {$ref: '#/components/schemas/Color'}}
        color_m: {type: object, additionalProperties: {$ref: '#/components/schemas/Color'}}
        color_u: {anyOf: [{$ref: '#/components/schemas/Color'}, {type: integer}]}
        size_f: {$ref: '#/components/schemas/Size'}
        size_a: {type: array, items: {$ref: '#/components/schemas/Size'}}
        size_m: {type: object, additionalProperties: {$ref: '#/components/schemas/Size'}}
        size_u: {anyOf: [{$ref: '#/components/schemas/Size'}, {type: integer}]}
        pet_f: {$ref: '#/components/schemas/Pet'}
        pet_a: {type: array, items: {$ref: '#/components/schemas/Pet'}}
        pet_m: {type: object, additionalProperties: {$ref: '#/components/schemas/Pet'}}
        pet_u: {anyOf: [{$ref: '#/components/schemas/Pet'}, {type: integer}]}

Output:

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

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, RootModel


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


class Color(Enum):
    red = 'red'
    NoneType_None = None


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


class Pet(BaseModel):
    id: int | None = None


class Use(BaseModel):
    name_f: Name
    name_a: list[Name]
    name_m: dict[str, Name]
    name_u: Name | int
    name_o: Name | None
    name_d: Name | None = None
    color_f: Color
    color_a: list[Color]
    color_m: dict[str, Color]
    color_u: Color | int
    size_f: Size
    size_a: list[Size]
    size_m: dict[str, Size]
    size_u: Size | int
    pet_f: Pet
    pet_a: list[Pet]
    pet_m: dict[str, Pet]
    pet_u: Pet | int
# generated by datamodel-codegen:
#   filename:  redundant_reference_null.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from enum import Enum

from pydantic import BaseModel, RootModel


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


class Color(Enum):
    red = 'red'
    NoneType_None = None


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


class Pet(BaseModel):
    id: int | None = None


class Use(BaseModel):
    name_f: Name | None
    name_a: list[Name | None]
    name_m: dict[str, Name | None]
    name_u: Name | int | None
    name_o: Name | None
    name_d: Name | None = None
    color_f: Color
    color_a: list[Color]
    color_m: dict[str, Color]
    color_u: Color | int
    size_f: Size
    size_a: list[Size]
    size_m: dict[str, Size]
    size_u: Size | int
    pet_f: Pet
    pet_a: list[Pet]
    pet_m: dict[str, Pet]
    pet_u: Pet | int

--order-constructor-fields-by

Order constructor fields by final names or by written defaults.

The --order-constructor-fields-by option takes one or more values, final-names and written-defaults, each a separate change; other output model types ignore them.

final-names applies to dataclasses.dataclass, pydantic_v2.dataclass and msgspec.Struct. A field that is renamed because it is named like its type, such as Bar: Bar, is renamed in every class of its family. Without the value the order of a class's constructor fields is decided while its module is processed, where the inherited field may not be renamed yet: a subclass that overrides it as a required field then reads as a new field after the inherited default, and is written keyword-only (kw_only=True), which moves it behind the positional fields and changes the first positional argument of the constructor. With the value the order is decided once every field has its final name, so the override takes the place of the inherited field and stays positional.

written-defaults changes msgspec.Struct and pydantic_v2.dataclass output under --strip-default-none, and under --use-default-factory-for-optional-nested-models --strip-default-none the order of dataclass and Pydantic dataclass fields beside nested models whose default factory a reference cycle drops. A Struct writes a default for every optional field: UNSET, or None when the type admits None, even where --strip-default-none strips the field's None default, and a Pydantic dataclass writes None for a type that admits None. Without the value such a field keeps its place among the fields without a default, as in earlier releases: it is keyword-only after an inherited default, and the fields are reordered or made keyword-only only when a required field would then follow a default (which the class rejects at import). With the value every optional field of a Struct goes after the required fields, in schema order, which changes the order of the constructor's positional arguments, and such a field stays positional after an inherited default (for a Pydantic dataclass together with final-names).

A pydantic.dataclass field whose stripped None default stays written, as its type admits None, counts as that default in a subclass with the value: a required field redeclaring it is written Field(...) (a msgspec.Struct writes the bare annotation, kind: str). Without the value the subclass field inherits the None default, as in earlier releases.

Usage

datamodel-codegen --input field_type_collision_inherited_modules --output-model-type pydantic_v2.dataclass --target-python-version 3.11 --order-constructor-fields-by final-names # (1)!
  1. --order-constructor-fields-by - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info:
  title: strip default none constructor order
  version: 1.0.0
paths: {}
components:
  schemas:
    Plain:
      type: object
      properties:
        a:
          type: string
    Nullable:
      type: [object, "null"]
      properties:
        a:
          type: string
    Kept:
      type: object
      required: [r]
      properties:
        n:
          anyOf:
            - $ref: '#/components/schemas/Plain'
            - type: "null"
        p:
          $ref: '#/components/schemas/Plain'
        q:
          type: string
        r:
          type: string
        d:
          type: string
          default: x
        e:
          type: [string, "null"]
    Spelling:
      type: object
      properties:
        d:
          type: string
          default: x
        n:
          anyOf:
            - $ref: '#/components/schemas/Plain'
            - type: "null"
        e:
          anyOf:
            - type: string
            - type: "null"
        t:
          type: [string, "null"]
    SpellingRequired:
      type: object
      properties:
        d:
          type: string
          default: x
        t:
          type: [string, "null"]
        n:
          anyOf:
            - $ref: '#/components/schemas/Plain'
            - type: "null"
        q:
          type: string
    M:
      type: object
      properties:
        d:
          type: string
          default: x
        n:
          $ref: '#/components/schemas/Nullable'
        q:
          type: string
    Earlier:
      type: object
      required: [r]
      properties:
        d:
          type: string
          default: x
        n:
          $ref: '#/components/schemas/Nullable'
        r:
          type: string
    Later:
      type: object
      required: [r]
      properties:
        d:
          type: string
          default: x
        n:
          $ref: '#/components/schemas/NullableLater'
        r:
          type: string
    UnionMember:
      type: object
      properties:
        u:
          anyOf:
            - $ref: '#/components/schemas/Nullable'
            - type: string
        l:
          type: array
          items:
            $ref: '#/components/schemas/Nullable'
        q:
          type: string
    Base:
      type: object
      properties:
        n:
          anyOf:
            - $ref: '#/components/schemas/Plain'
            - type: "null"
    Child:
      allOf:
        - $ref: '#/components/schemas/Base'
        - type: object
          required: [r]
          properties:
            r:
              type: string
            q:
              type: string
    AliasedRequired:
      type: object
      required: [R-1]
      properties:
        n:
          anyOf:
            - $ref: '#/components/schemas/Plain'
            - type: "null"
        R-1:
          type: string
    WithDefault:
      type: object
      properties:
        d:
          type: string
          default: x
    KeptAfterInheritedDefault:
      allOf:
        - $ref: '#/components/schemas/WithDefault'
        - type: object
          properties:
            n:
              anyOf:
                - $ref: '#/components/schemas/Plain'
                - type: "null"
    Cat:
      type: object
      required: [lives]
      properties:
        kind:
          anyOf:
            - type: string
            - type: "null"
        lives:
          type: integer
    NamedCat:
      allOf:
        - $ref: '#/components/schemas/Cat'
        - type: object
          required: [kind]
          properties:
            kind:
              type: string
            name:
              type: string
    NullableLater:
      type: [object, "null"]
      properties:
        a:
          type: string

Output:

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

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType, field


class Plain(Struct):
    a: str | UnsetType = UNSET


class Nullable(Struct):
    a: str | UnsetType = UNSET


class Kept(Struct):
    r: str
    n: Plain | None | UnsetType = UNSET
    p: Plain | UnsetType = UNSET
    q: str | UnsetType = UNSET
    d: str | UnsetType = 'x'
    e: str | None | UnsetType = UNSET


class Spelling(Struct):
    d: str | UnsetType = 'x'
    n: Plain | None | UnsetType = UNSET
    e: str | None | UnsetType = UNSET
    t: str | None | UnsetType = UNSET


class SpellingRequired(Struct):
    d: str | UnsetType = 'x'
    t: str | None | UnsetType = UNSET
    n: Plain | None | UnsetType = UNSET
    q: str | UnsetType = UNSET


class M(Struct):
    d: str | UnsetType = 'x'
    n: Nullable | None | UnsetType = UNSET
    q: str | UnsetType = UNSET


class Earlier(Struct):
    r: str
    d: str | UnsetType = 'x'
    n: Nullable | None | UnsetType = UNSET


class UnionMember(Struct):
    u: Nullable | None | str | UnsetType = UNSET
    l: list[Nullable | None] | UnsetType = UNSET
    q: str | UnsetType = UNSET


class Base(Struct):
    n: Plain | None | UnsetType = UNSET


class Child(Base, kw_only=True):
    r: str
    q: str | UnsetType = UNSET


class AliasedRequired(Struct):
    R_1: str = field(name='R-1')
    n: Plain | None | UnsetType = UNSET


class WithDefault(Struct):
    d: str | UnsetType = 'x'


class KeptAfterInheritedDefault(WithDefault):
    n: Plain | None | UnsetType = UNSET


class Cat(Struct):
    lives: int
    kind: str | None | UnsetType = UNSET


class NamedCat(Cat):
    kind: str | None
    name: str | UnsetType = UNSET


class NullableLater(Struct):
    a: str | UnsetType = UNSET


class Later(Struct):
    r: str
    d: str | UnsetType = 'x'
    n: NullableLater | None | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  strip_default_none_constructor_order.yaml
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType, field


class Plain(Struct):
    a: str | UnsetType = UNSET


class Nullable(Struct):
    a: str | UnsetType = UNSET


class Kept(Struct):
    r: str
    n: Plain | None | UnsetType = UNSET
    p: Plain | UnsetType = UNSET
    q: str | UnsetType = UNSET
    e: str | None | UnsetType = UNSET
    d: str | UnsetType = 'x'


class Spelling(Struct):
    n: Plain | None | UnsetType = UNSET
    e: str | None | UnsetType = UNSET
    t: str | None | UnsetType = UNSET
    d: str | UnsetType = 'x'


class SpellingRequired(Struct):
    t: str | None | UnsetType = UNSET
    n: Plain | None | UnsetType = UNSET
    q: str | UnsetType = UNSET
    d: str | UnsetType = 'x'


class M(Struct):
    n: Nullable | None | UnsetType = UNSET
    q: str | UnsetType = UNSET
    d: str | UnsetType = 'x'


class Earlier(Struct):
    r: str
    n: Nullable | None | UnsetType = UNSET
    d: str | UnsetType = 'x'


class UnionMember(Struct):
    u: Nullable | None | str | UnsetType = UNSET
    l: list[Nullable | None] | UnsetType = UNSET
    q: str | UnsetType = UNSET


class Base(Struct):
    n: Plain | None | UnsetType = UNSET


class Child(Base, kw_only=True):
    r: str
    q: str | UnsetType = UNSET


class AliasedRequired(Struct):
    R_1: str = field(name='R-1')
    n: Plain | None | UnsetType = UNSET


class WithDefault(Struct):
    d: str | UnsetType = 'x'


class KeptAfterInheritedDefault(WithDefault, kw_only=True):
    n: Plain | None | UnsetType = UNSET


class Cat(Struct):
    lives: int
    kind: str | None | UnsetType = UNSET


class NamedCat(Cat):
    kind: str | None
    name: str | UnsetType = UNSET


class NullableLater(Struct):
    a: str | UnsetType = UNSET


class Later(Struct):
    r: str
    n: NullableLater | None | UnsetType = UNSET
    d: str | UnsetType = 'x'

Input Schema:

# a.json
{"title":"Base","type":"object","properties":{"Bar":{"$ref":"#/definitions/Bar"}},"definitions":{"Bar":{"type":"object","properties":{"x":{"type":"integer"}}}}}

# b.json
{"title":"Child","allOf":[{"$ref":"a.json"}],"type":"object","required":["Bar"],"properties":{"Zed":{"type":"string"}}}

Output:

# __init__.py
# generated by datamodel-codegen:
#   filename:  field_type_collision_inherited_modules

# a.py
# generated by datamodel-codegen:
#   filename:  a.json

from __future__ import annotations

from pydantic import Field
from pydantic.dataclasses import dataclass


@dataclass
class Bar:
    x: int | None = None


@dataclass
class Base:
    Bar_1: Bar | None = Field(None, alias='Bar')

# b.py
# generated by datamodel-codegen:
#   filename:  b.json

from __future__ import annotations

from pydantic import Field
from pydantic.dataclasses import dataclass

from . import a
from .a import Base


@dataclass
class Child(Base):
    Bar_1: a.Bar = Field(..., alias='Bar')
    Zed: str | None = None
# __init__.py
# generated by datamodel-codegen:
#   filename:  field_type_collision_inherited_modules

# a.py
# generated by datamodel-codegen:
#   filename:  a.json

from __future__ import annotations

from pydantic import Field
from pydantic.dataclasses import dataclass


@dataclass
class Bar:
    x: int | None = None


@dataclass
class Base:
    Bar_1: Bar | None = Field(None, alias='Bar')

# b.py
# generated by datamodel-codegen:
#   filename:  b.json

from __future__ import annotations

from pydantic import Field
from pydantic.dataclasses import dataclass

from . import a
from .a import Base


@dataclass
class Child(Base):
    Bar_1: a.Bar = Field(..., alias='Bar', kw_only=True)
    Zed: str | None = None

--output-model-type

Select the output model type (Pydantic v2, Pydantic v2 dataclass, dataclasses, TypedDict, msgspec).

The --output-model-type flag specifies which Python data model framework to use for the generated code. Supported values include pydantic_v2.BaseModel, pydantic_v2.dataclass, dataclasses.dataclass, typing.TypedDict, and msgspec.Struct.

See also: Output Model Types

Option relationships:

  • Implies: When --output-model-type=msgspec.Struct, --use-annotated enabled

Usage

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

Input Schema:

{
    "$schema": "http://json-schema.org/schema#",
    "type": "object",
    "properties": {
        "my_obj": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "items": {
                        "type": [
                            "array",
                            "null"
                        ]
                    }
                },
                "required": [
                    "items"
                ]
            }
        }
    },
    "required": [
        "my_obj"
    ]
}

Output:

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

from __future__ import annotations

from typing import Any

from pydantic import BaseModel


class MyObjItem(BaseModel):
    items: list[Any] | None


class Model(BaseModel):
    my_obj: list[MyObjItem]

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, 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):
    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):
    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):
    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):
    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):
    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):
    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()
# generated by datamodel-codegen:
#   filename:  simple-star-wars.graphql
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal, TypeAlias

Boolean: TypeAlias = bool
"""
The `Boolean` scalar type represents `true` or `false`.
"""


ID: TypeAlias = 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: TypeAlias = int
"""
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
"""


String: TypeAlias = 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.
"""


@dataclass
class Film:
    characters: list[Person]
    characters_ids: list[ID]
    director: String
    episode_id: Int
    id: ID
    opening_crawl: String
    planets: list[Planet]
    planets_ids: list[ID]
    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]
    producer: String | None = None
    typename__: Literal['Film'] | None = 'Film'


@dataclass
class Person:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    species: list[Species]
    species_ids: list[ID]
    starships: list[Starship]
    starships_ids: list[ID]
    vehicles: list[Vehicle]
    vehicles_ids: list[ID]
    birth_year: String | None = None
    eye_color: String | None = None
    gender: String | None = None
    hair_color: String | None = None
    height: Int | None = None
    homeworld: Planet | None = None
    homeworld_id: ID | None = None
    mass: Int | None = None
    skin_color: String | None = None
    typename__: Literal['Person'] | None = 'Person'


@dataclass
class Planet:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    residents: list[Person]
    residents_ids: list[ID]
    climate: String | None = None
    diameter: String | None = None
    gravity: String | None = None
    orbital_period: String | None = None
    population: String | None = None
    rotation_period: String | None = None
    surface_water: String | None = None
    terrain: String | None = None
    typename__: Literal['Planet'] | None = 'Planet'


@dataclass
class Species:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    people: list[Person]
    people_ids: list[ID]
    average_height: String | None = None
    average_lifespan: String | None = None
    classification: String | None = None
    designation: String | None = None
    eye_colors: String | None = None
    hair_colors: String | None = None
    language: String | None = None
    skin_colors: String | None = None
    typename__: Literal['Species'] | None = 'Species'


@dataclass
class Starship:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    pilots: list[Person]
    pilots_ids: list[ID]
    MGLT: String | None = None
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    hyperdrive_rating: String | None = None
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    passengers: String | None = None
    starship_class: String | None = None
    typename__: Literal['Starship'] | None = 'Starship'


@dataclass
class Vehicle:
    films: list[Film]
    films_ids: list[ID]
    id: ID
    name: String
    pilots: list[Person]
    pilots_ids: list[ID]
    cargo_capacity: String | None = None
    consumables: String | None = None
    cost_in_credits: String | None = None
    crew: String | None = None
    length: String | None = None
    manufacturer: String | None = None
    max_atmosphering_speed: String | None = None
    model: String | None = None
    passengers: String | None = None
    vehicle_class: String | None = None
    typename__: Literal['Vehicle'] | None = 'Vehicle'

--parent-scoped-naming

Namespace models by their parent scope to avoid naming conflicts.

The --parent-scoped-naming flag prefixes model names with their parent scope (operation/path/parameter) to prevent name collisions when the same model name appears in different contexts within an OpenAPI specification.

Deprecated: --parent-scoped-naming is deprecated. Use --naming-strategy parent-prefixed instead.

Option relationships:

Usage

datamodel-codegen --input duplicate_models2.yaml --parent-scoped-naming --use-operation-id-as-name --openapi-scopes paths schemas parameters # (1)!
  1. --parent-scoped-naming - 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: Get pet
      operationId: getPets
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
  /cars:
    get:
      summary: Get car
      operationId: getCar
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Cars"

components:
  schemas:
    Pet:
      required:
        - id
        - name
        - type
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
        type:
          type: string
          enum: [ 'pet' ]
        details:
          type: object
          properties:
            race: { type: string }
    Car:
      required:
        - id
        - name
        - type
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
        type:
          type: string
          enum: [ 'car' ]
        details:
          type: object
          properties:
            brand: { type: string }

Output:

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

from __future__ import annotations

from enum import Enum
from typing import Any

from pydantic import BaseModel, RootModel


class PetType(Enum):
    pet = 'pet'


class PetDetails(BaseModel):
    race: str | None = None


class Pet(BaseModel):
    id: int
    name: str
    tag: str | None = None
    type: PetType
    details: PetDetails | None = None


class CarType(Enum):
    car = 'car'


class CarDetails(BaseModel):
    brand: str | None = None


class Car(BaseModel):
    id: int
    name: str
    tag: str | None = None
    type: CarType
    details: CarDetails | None = None


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

--pin-aliases-with-alias-generator

Decide a field's alias by the alias generator its model applies.

The --pin-aliases-with-alias-generator flag only applies to --output-model-type pydantic_v2.BaseModel and pydantic_v2.dataclass; other output model types ignore it.

Pydantic applies the alias_generator in the config of a model, and a subclass applies the one in the config of its base. Without the flag the generated aliases are decided from the generator of the whole run (--alias-generator or the template data key alias_generator) even where the model does not apply it, a dataclass renders none, and the alias_generator in the config of a model, of its base or of a dataclass is not read. A field may then lose the alias that carries the document's property name, or keep an alias the generator already produces.

With the flag the aliases follow the generator the model applies: the one in its config or in the config it inherits, none for alias_generator: null, and none for a dataclass whose config names none. For a --target-pydantic-version older than 2.8, whose generator algorithms can differ from the ones dcg runs, the generated alias is written on every field of a dataclass whose config names a generator, as it is for a BaseModel.

Usage

datamodel-codegen --input alias_generator.json --output-model-type pydantic_v2.dataclass --snake-case-field --pin-aliases-with-alias-generator --extra-template-data jsonschema/extra_data_alias_generator.json --target-pydantic-version 2 # (1)!
  1. --pin-aliases-with-alias-generator - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "AliasGeneratorModel",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    },
    "foo_bar": {
      "type": "string"
    },
    "weird-url": {
      "type": "integer"
    }
  },
  "required": ["firstName", "foo_bar", "weird-url"]
}

Output:

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

from __future__ import annotations

from pydantic import AliasChoices, Field
from pydantic.dataclasses import dataclass


@dataclass
class AliasGeneratorModel:
    foo_bar: str
    first_name: str = Field(..., alias='firstName')
    last_name: str | None = Field(None, alias='lastName')
    weird_url: int = Field(
        ..., serialization_alias='weird-url', validation_alias=AliasChoices('weird-url')
    )
# generated by datamodel-codegen:
#   filename:  alias_generator.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import AliasChoices, Field
from pydantic.dataclasses import dataclass


@dataclass
class AliasGeneratorModel:
    first_name: str
    foo_bar: str = Field(..., alias='foo_bar')
    last_name: str | None = None
    weird_url: int = Field(
        ..., serialization_alias='weird-url', validation_alias=AliasChoices('weird-url')
    )

--read-nullable-beside-type-list

Write the null that nullable: true declares beside a type list into the root model.

A schema whose type list holds an object and another type is generated as a model of its properties and a root model of the union of the types. Under --strict-nullable or --use-missing-sentinel its fields write the null their schema declares, and so does that root model for a type list holding "null". Without the option the root model ignores nullable: true and rejects null, as in 0.86.0; with --read-nullable-beside-type-list it admits None as the type list holding "null" does.

Usage

datamodel-codegen --input null_multiple_types_oas30.yaml --use-missing-sentinel --read-nullable-beside-type-list # (1)!
  1. --read-nullable-beside-type-list - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info:
  title: t
  version: "1"
paths: {}
components:
  schemas:
    U:
      type: [object, string]
      nullable: true
      properties:
        x:
          type: integer
    V:
      type: [object, string, "null"]
      properties:
        x:
          type: integer
    W:
      type: [object, string]
      properties:
        x:
          type: integer
    Model:
      type: object
      properties:
        u:
          $ref: '#/components/schemas/U'
        v:
          $ref: '#/components/schemas/V'
        w:
          $ref: '#/components/schemas/W'

Output:

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

from __future__ import annotations

from pydantic import BaseModel, RootModel
from pydantic.experimental.missing_sentinel import MISSING


class U(BaseModel):
    x: int | MISSING = MISSING


class U1(RootModel[U | str | None | MISSING]):
    root: U | str | None | MISSING = MISSING


class V(BaseModel):
    x: int | MISSING = MISSING


class V1(RootModel[V | str | None | MISSING]):
    root: V | str | None | MISSING = MISSING


class W(BaseModel):
    x: int | MISSING = MISSING


class W1(RootModel[W | str]):
    root: W | str


class Model(BaseModel):
    u: U1 | MISSING = MISSING
    v: V1 | None | MISSING = MISSING
    w: W1 | MISSING = MISSING
# generated by datamodel-codegen:
#   filename:  null_multiple_types_oas30.yaml

from __future__ import annotations

from pydantic import BaseModel, RootModel
from pydantic.experimental.missing_sentinel import MISSING


class U(BaseModel):
    x: int | MISSING = MISSING


class U1(RootModel[U | str | MISSING]):
    root: U | str | MISSING = MISSING


class V(BaseModel):
    x: int | MISSING = MISSING


class V1(RootModel[V | str | None | MISSING]):
    root: V | str | None | MISSING = MISSING


class W(BaseModel):
    x: int | MISSING = MISSING


class W1(RootModel[W | str]):
    root: W | str


class Model(BaseModel):
    u: U1 | MISSING = MISSING
    v: V1 | None | MISSING = MISSING
    w: W1 | MISSING = MISSING

--remove-unused-models-beside-type-overrides

Remove the unused models from a module that a model-level --type-overrides key changes.

A model that nothing uses any more, such as a root model --collapse-root-models inlined into every field that named it, leaves the output. In a module from which a model-level --type-overrides key ({"Other": "collections.OrderedDict"}) takes the model it replaces, such models stay written, unused: class Code(RootModel[constr(max_length=3)]) beside code: constr(max_length=3) | None. With this option they leave that module too, as they leave every other module.

Usage

datamodel-codegen --input collapsed_roots_beside_type_overrides.json --collapse-root-models --collapse-root-models-name-strategy child --type-overrides '{"Other": "collections.OrderedDict"}' --remove-unused-models-beside-type-overrides # (1)!
  1. --remove-unused-models-beside-type-overrides - the option documented here
Examples

Input Schema:

{
  "title": "Model",
  "type": "object",
  "properties": {
    "code": {"$ref": "#/$defs/Code"},
    "codes": {"type": "array", "items": {"$ref": "#/$defs/Codes"}},
    "other": {"$ref": "#/$defs/Other"}
  },
  "$defs": {
    "Code": {"type": "string", "maxLength": 3},
    "Codes": {"$ref": "#/$defs/Name"},
    "Name": {"type": "object", "properties": {"first": {"type": "string"}}},
    "Other": {"type": "object", "properties": {"a": {"type": "string"}}}
  }
}

Output:

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

from __future__ import annotations

from collections import OrderedDict

from pydantic import BaseModel, constr


class Name(BaseModel):
    first: str | None = None


class Model(BaseModel):
    code: constr(max_length=3) | None = None
    codes: list[Name] | None = None
    other: OrderedDict | None = None
# generated by datamodel-codegen:
#   filename:  collapsed_roots_beside_type_overrides.json

from __future__ import annotations

from collections import OrderedDict

from pydantic import BaseModel, RootModel, constr


class Code(RootModel[constr(max_length=3)]):
    root: constr(max_length=3)


class Name(BaseModel):
    first: str | None = None


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


class Model(BaseModel):
    code: constr(max_length=3) | None = None
    codes: list[Name] | None = None
    other: OrderedDict | None = None

--reuse-model

Reuse identical model definitions instead of generating duplicates.

The --reuse-model flag detects identical enum or model definitions across the schema and generates a single shared definition, reducing code duplication in the output.

Related: --collapse-root-models

See also: Model Reuse and Deduplication

Usage

datamodel-codegen --input duplicate_enum.json --reuse-model # (1)!
  1. --reuse-model - 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 = 'dog'
    pet: Animal | None = 'cat'
    redistribute: list[RedistributeEnum] | None = None


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

--reuse-scope

Scope for model reuse detection (root or tree).

The --reuse-scope flag configures the code generation behavior.

See also: Model Reuse and Deduplication

Option relationships:

  • Requires: When --reuse-scope=tree, --reuse-model enabled - --reuse-scope=tree has no effect without --reuse-model.

Usage

datamodel-codegen --input reuse_scope_tree --reuse-model --reuse-scope tree # (1)!
  1. --reuse-scope - the option documented here
Examples

Input Schema:

# schema_a.json
{
  "type": "object",
  "properties": {
    "data": { "$ref": "#/$defs/SharedModel" }
  },
  "$defs": {
    "SharedModel": {
      "type": "object",
      "properties": {
        "id": { "type": "integer" },
        "name": { "type": "string" }
      }
    }
  }
}

# schema_b.json
{
  "type": "object",
  "properties": {
    "info": { "$ref": "#/$defs/SharedModel" }
  },
  "$defs": {
    "SharedModel": {
      "type": "object",
      "properties": {
        "id": { "type": "integer" },
        "name": { "type": "string" }
      }
    }
  }
}

Output:

# __init__.py
# generated by datamodel-codegen:
#   filename:  reuse_scope_tree
#   timestamp: 2019-07-26T00:00:00+00:00

# schema_a.py
# generated by datamodel-codegen:
#   filename:  reuse_scope_tree
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from pydantic import BaseModel

from .shared import SharedModel as SharedModel_1


class SharedModel(SharedModel_1):
    pass


class Model(BaseModel):
    data: SharedModel | None = None

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

from __future__ import annotations

from pydantic import BaseModel

from . import shared


class Model(BaseModel):
    info: shared.SharedModel | None = None

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

from __future__ import annotations

from pydantic import BaseModel


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

--singularize-last-word-of-item-names

Name the item model of an array by singularizing only the last word of its name.

The item model of an array property is named by singularizing the property name. Without the option the whole name is singularized as one word, which goes wrong for some endings: actions_caches gives ActionsCach and payment_status gives PaymentStatu. With --singularize-last-word-of-item-names only the last word is singularized, ActionsCache, and a last word without a singular takes the Item suffix, PaymentStatusItem.

Related: --disable-appending-item-suffix

Usage

datamodel-codegen --input singularize_last_word_of_item_names.yaml --singularize-last-word-of-item-names # (1)!
  1. --singularize-last-word-of-item-names - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info: {title: singular, version: "1"}
paths: {}
components:
  schemas:
    ActionsCacheList:
      type: object
      properties:
        actions_caches:
          type: array
          items:
            type: object
            properties:
              id: {type: integer}
        payment_status:
          type: array
          items:
            type: object
            properties:
              s: {type: string}
        shipping_addresses:
          type: array
          items:
            type: object
            properties:
              city: {type: string}

Output:

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

from __future__ import annotations

from pydantic import BaseModel


class ActionsCache(BaseModel):
    id: int | None = None


class PaymentStatusItem(BaseModel):
    s: str | None = None


class ShippingAddress(BaseModel):
    city: str | None = None


class ActionsCacheList(BaseModel):
    actions_caches: list[ActionsCache] | None = None
    payment_status: list[PaymentStatusItem] | None = None
    shipping_addresses: list[ShippingAddress] | None = None
# generated by datamodel-codegen:
#   filename:  singularize_last_word_of_item_names.yaml

from __future__ import annotations

from pydantic import BaseModel


class ActionsCach(BaseModel):
    id: int | None = None


class PaymentStatu(BaseModel):
    s: str | None = None


class ShippingAddress(BaseModel):
    city: str | None = None


class ActionsCacheList(BaseModel):
    actions_caches: list[ActionsCach] | None = None
    payment_status: list[PaymentStatu] | None = None
    shipping_addresses: list[ShippingAddress] | None = None

--skip-root-model

Skip generation of root model when schema contains nested definitions.

The --skip-root-model flag prevents generating a model for the root schema object when the schema primarily contains reusable definitions. This is useful when the root object is just a container for $defs and not a meaningful model itself.

Usage

datamodel-codegen --input skip_root_model_test.json --output-model-type pydantic_v2.BaseModel --skip-root-model # (1)!
  1. --skip-root-model - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "_Placeholder",
  "type": "null",
  "$defs": {
    "Person": {
      "type": "object",
      "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"}
      },
      "required": ["name"]
    }
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: int | None = None

--strict-nullable

Treat default field as a non-nullable field.

The --strict-nullable flag ensures that fields with default values are generated with their exact schema type (non-nullable), rather than being made nullable.

This is particularly useful when combined with --use-default to generate models where optional fields have defaults but cannot accept None values.

Related: --use-default

Usage

datamodel-codegen --input nullable.yaml --strict-nullable # (1)!
  1. --strict-nullable - the option documented here
Examples

Input Schema:

openapi: 3.0.3
info:
  version: 1.0.0
  title: testapi
  license:
    name: proprietary
servers: []
paths: {}
components:
  schemas:
    TopLevel:
      type: object
      properties:
        cursors:
          type: object
          properties:
            prev:
              type: string
              nullable: true
            next:
              type: string
              default: last
            index:
              type: number
            tag:
              type: string
          required:
          - prev
          - index
      required:
      - cursors
    User:
      type: object
      properties:
        info:
          type: object
          properties:
            name:
              type: string
          required:
            - name
      required:
        - info
    apis:
      type: array
      nullable: true
      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"
            nullable: true
          apiDocumentationUrl:
            type: string
            format: uri
            description: A URL to the API console for each API
            nullable: true
    email:
      type: array
      items:
        type: object
        properties:
          author:
            type: string
          address:
            type: string
            description: email address
          description:
            type: string
            default: empty
          tag:
            type: string
        required:
          - author
          - address
    id:
      type: integer
      default: 1
    description:
      type: string
      nullable: true
      default: example
    name:
      type: string
      nullable: true
    tag:
      type: string
    notes:
      type: object
      properties:
        comments:
          type: array
          items:
              type: string
          default_factory: list
          nullable: false
    options:
      type: object
      properties:
        comments:
          type: array
          items:
              type: string
              nullable: true
        oneOfComments:
           type: array
           items:
               oneOf:
                - type: string
                - type: number
               nullable: true
        simpleUnion:
          oneOf:
            - type: string
            - type: number
      required:
        - comments
        - oneOfComments

Output:

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

from __future__ import annotations

from pydantic import AnyUrl, BaseModel, Field, RootModel


class Cursors(BaseModel):
    prev: str | None = Field(...)
    next: str = 'last'
    index: float
    tag: str | None = None


class TopLevel(BaseModel):
    cursors: Cursors


class Info(BaseModel):
    name: str


class User(BaseModel):
    info: Info


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] | None]):
    root: list[Api] | None = Field(...)


class EmailItem(BaseModel):
    author: str
    address: str = Field(..., description='email address')
    description: str = 'empty'
    tag: str | None = None


class Email(RootModel[list[EmailItem]]):
    root: list[EmailItem]


class Id(RootModel[int]):
    root: int = 1


class Description(RootModel[str | None]):
    root: str | None = 'example'


class Name(RootModel[str | None]):
    root: str | None = None


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


class Notes(BaseModel):
    comments: list[str] = Field(default_factory=list)


class Options(BaseModel):
    comments: list[str | None]
    oneOfComments: list[str | float | None]
    simpleUnion: str | float | None = None

--strip-default-none

Remove fields with None as default value from generated models.

The --strip-default-none option removes fields that have None as their default value from the generated models. This results in cleaner model definitions by excluding optional fields that default to None.

The option has no effect on msgspec.Struct output. A Struct defaults an omitted field to UNSET, not None, so there is no None default to strip. Only a field that nullable: true makes nullable under --strict-nullable defaults to None, and that default stays, as the field's type admits None.

Usage

datamodel-codegen --input api.yaml --strip-default-none # (1)!
  1. --strip-default-none - 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 pydantic import AnyUrl, BaseModel, Field, RootModel


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


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


class User(BaseModel):
    id: int
    name: str
    tag: str | 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(description='To be used as a dataset parameter value')
    apiVersionNumber: str | None = Field(
        description='To be used as a version parameter value'
    )
    apiUrl: AnyUrl | None = Field(description="The URL describing the dataset's fields")
    apiDocumentationUrl: AnyUrl | None = Field(
        description='A URL to the API console for each API'
    )


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


class Event(BaseModel):
    name: str | None


class Result(BaseModel):
    event: Event | None

--tag-msgspec-by-payload-name

Tag the structs of a msgspec discriminated union with the property name of the document.

The --tag-msgspec-by-payload-name flag only applies to --output-model-type msgspec.Struct; other output model types ignore it.

msgspec reads the tag from the payload under tag_field. Without the flag, the structs whose discriminator is a single literal take the Python name the property resolves to: a property named pet-kind is tagged by pet_kind, which msgspec looks for in the payload instead, so the union decodes nothing. With the flag, tag_field is the property name the document carries (pet-kind). --use-msgspec-tagged-unions tags by the document's property name too.

Usage

datamodel-codegen --input discriminator_msgspec_wire_name.json --tag-msgspec-by-payload-name --output-model-type msgspec.Struct # (1)!
  1. --tag-msgspec-by-payload-name - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "Cat": {
      "type": "object",
      "properties": {
        "pet-kind": {
          "const": "cat"
        },
        "name": {
          "type": "string"
        }
      },
      "required": [
        "pet-kind"
      ]
    },
    "Dog": {
      "type": "object",
      "properties": {
        "pet-kind": {
          "const": "dog"
        },
        "bark": {
          "type": "string"
        }
      },
      "required": [
        "pet-kind"
      ]
    }
  },
  "title": "Model",
  "type": "object",
  "properties": {
    "pet": {
      "oneOf": [
        {
          "$ref": "#/$defs/Cat"
        },
        {
          "$ref": "#/$defs/Dog"
        }
      ],
      "discriminator": {
        "propertyName": "pet-kind"
      }
    }
  }
}

Output:

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

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType


class Cat(Struct, tag_field='pet-kind', tag='cat'):
    name: str | UnsetType = UNSET


class Dog(Struct, tag_field='pet-kind', tag='dog'):
    bark: str | UnsetType = UNSET


class Model(Struct):
    pet: Cat | Dog | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  discriminator_msgspec_wire_name.json

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType


class Cat(Struct, tag_field='pet_kind', tag='cat'):
    name: str | UnsetType = UNSET


class Dog(Struct, tag_field='pet_kind', tag='dog'):
    bark: str | UnsetType = UNSET


class Model(Struct):
    pet: Cat | Dog | UnsetType = UNSET

--target-pydantic-version

Target Pydantic version for generated code compatibility.

The --target-pydantic-version flag chooses the oldest Pydantic the generated code must run on. Output never depends on the Pydantic installed with datamodel-code-generator.

  • unset: the newest supported feature forms, the same as 2.12; config key naming is unchanged and keeps populate_by_name=True like 2, and --use-missing-sentinel keeps the experimental MISSING import
  • 2: Pydantic 2.0.3+ compatible forms, such as populate_by_name=True, Field(...) string constraints, json_schema_extra for deprecated fields, and dictionary-key models defined first
  • 2.11: Pydantic 2.11+ forms, such as validate_by_name=True, StringConstraints, Field(deprecated=True), and TypeAliasType dataclass aliases
  • 2.12: The 2.11 forms plus features that require Pydantic 2.12+, such as --use-missing-sentinel
  • 2.14: The 2.12 forms, with --use-missing-sentinel importing MISSING from pydantic instead of the pydantic.experimental.missing_sentinel path that Pydantic 2.14 deprecates, Python's regex engine for bytes patterns the Rust engine rejects, which Pydantic compiles from 2.14 on, and required pydantic_v2.dataclass fields written as = Field(...) placed before the fields with defaults of the same class, the order inspect.signature needs on Pydantic 2.13+

Constructs that have no older form, such as regex_engine or a type statement, are written for every target; when the target is older than the release they need, the generation warns once with that release.

See Output Model Types for every affected form.

Usage

datamodel-codegen --input person.json --target-pydantic-version 2.11 --allow-population-by-field-name --output-model-type pydantic_v2.BaseModel # (1)!
  1. --target-pydantic-version - 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, ConfigDict, Field, conint


class Person(BaseModel):
    model_config = ConfigDict(
        validate_by_name=True,
    )
    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)

--target-python-version

Target Python version for generated code syntax and imports.

The --target-python-version flag controls Python version-specific syntax:

  • Python 3.10-3.11: Uses X | None union operator, TypeAlias annotation
  • Python 3.12+: Uses type statement for type aliases
  • Python 3.13+: Imports ReadOnly for read-only TypedDict keys from typing
  • Python 3.14+: Native deferred annotations; from __future__ import annotations only when needed
  • Python 3.15+: Imports TypedDict with closed and extra_items (PEP 728) from typing

This affects import statements and type annotation syntax in generated code.

See also: CI/CD Integration, Output Model Types, Python Version Compatibility, Root Models and Type Aliases

Usage

datamodel-codegen --input person.json --target-python-version 3.10 --use-standard-collections # (1)!
  1. --target-python-version - 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)

--union-mode

Union mode for combining anyOf/oneOf schemas (smart or left_to_right).

The --union-mode flag sets Pydantic's union_mode on generated union fields. Discriminated unions are not given a union_mode: Pydantic validates them by their discriminator tag, a separate mode that cannot be combined with smart or left_to_right.

Option relationships:

  • Requires: --output-model-type = pydantic_v2.BaseModel - --union-mode is only supported for --output-model-type pydantic_v2.BaseModel.

Usage

datamodel-codegen --input combine_any_of_object.json --union-mode left_to_right --output-model-type pydantic_v2.BaseModel # (1)!
  1. --union-mode - the option documented here
Examples

Input Schema:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "title": "My schema",
    "additionalProperties": true,
    "properties": {
        "AddressLine1": { "type": "string" },
        "AddressLine2": { "type": "string" },
        "City":         { "type": "string" }
    },
    "required": [ "AddressLine1" ],
    "anyOf": [
        {
            "type": "object",
            "properties": {
                "State":   { "type": "string" },
                "ZipCode": { "type": "string" }
            },
            "required": [ "ZipCode" ]
        },
        {
            "type": "object",
            "properties": {
                "County":   { "type": "string" },
                "PostCode": { "type": "string" }
            },
            "required": [ "PostCode" ]
        },
        { "$ref": "#/definitions/US" }
    ],
    "definitions": {
        "US":  {
            "type": "object",
            "properties": {
                "County":   { "type": "string" },
                "PostCode": { "type": "string" }
            },
            "required": [ "PostCode" ]
        }
    }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, ConfigDict, Field, RootModel


class MySchema1(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    AddressLine1: str
    AddressLine2: str | None = None
    City: str | None = None
    State: str | None = None
    ZipCode: str


class MySchema2(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    AddressLine1: str
    AddressLine2: str | None = None
    City: str | None = None
    County: str | None = None
    PostCode: str


class US(BaseModel):
    County: str | None = None
    PostCode: str


class MySchema3(US):
    model_config = ConfigDict(
        extra='allow',
    )
    AddressLine1: str
    AddressLine2: str | None = None
    City: str | None = None


class MySchema(RootModel[MySchema1 | MySchema2 | MySchema3]):
    root: MySchema1 | MySchema2 | MySchema3 = Field(
        ..., title='My schema', union_mode='left_to_right'
    )

--use-default

Use default values from schema in generated models.

The --use-default flag allows required fields with default values to be generated with their defaults, making them optional to provide when instantiating the model.

When --strict-nullable is enabled, the field type still follows the schema's nullability. For example, a required string field with a default is generated as str = 'value', not str | None = 'value', unless the schema allows null.

Related: --strict-nullable

Usage

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

Input Schema:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "title": "Use default with const",
    "properties": {
        "foo": {
            "const": "foo"
        },
        "bool_default": {
            "type": "boolean",
            "const": true,
            "default": false
        },
        "int_default": {
            "type": "integer",
            "const": 3,
            "default": 0
        },
        "str_default": {
            "type": "string",
            "const": "fast",
            "default": ""
        }
    }
}

Output:

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

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel


class UseDefaultWithConst(BaseModel):
    foo: Literal['foo'] | None = None
    bool_default: Literal[True] = False
    int_default: Literal[3] = 0
    str_default: Literal['fast'] = ''

--use-default-factory-for-optional-nested-models

Generate default_factory for optional nested model fields.

The --use-default-factory-for-optional-nested-models flag generates default_factory for optional nested model fields instead of None default: - Dataclasses: field: Model | None = field(default_factory=Model) - Pydantic: field: Model | None = Field(default_factory=Model) - msgspec: field: Model | UnsetType = field(default_factory=Model)

When a built-in generated child has required constructor fields, including inherited fields, the field keeps its usual None or UNSET default. The child's required fields remain required. With --strip-default-none, the usual omission behavior can instead require the parent field to be supplied explicitly. Existing defaults enabled by --use-default and fields excluded from the constructor are respected. Custom root templates, decorators, and opaque base classes keep their existing factory behavior. Constructors and validators are not executed to determine whether a factory is usable.

Usage

datamodel-codegen --input default_factory_nested_model.json --use-default-factory-for-optional-nested-models # (1)!
  1. --use-default-factory-for-optional-nested-models - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "name": {"type": "string"},
    "address": {"$ref": "#/$defs/Address"},
    "contact": {"$ref": "#/$defs/Contact"}
  },
  "required": ["name"],
  "$defs": {
    "Address": {
      "type": "object",
      "properties": {
        "street": {"type": "string"},
        "city": {"type": "string"}
      }
    },
    "Contact": {
      "type": "object",
      "properties": {
        "email": {"type": "string"},
        "phone": {"type": "string"}
      }
    }
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field


class Address(BaseModel):
    street: str | None = None
    city: str | None = None


class Contact(BaseModel):
    email: str | None = None
    phone: str | None = None


class Model(BaseModel):
    name: str
    address: Address | None = Field(default_factory=Address)
    contact: Contact | None = Field(default_factory=Contact)
# generated by datamodel-codegen:
#   filename:  default_factory_nested_model.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class Address:
    street: str | None = None
    city: str | None = None


@dataclass
class Contact:
    email: str | None = None
    phone: str | None = None


@dataclass
class Model:
    name: str
    address: Address | None = field(default_factory=Address)
    contact: Contact | None = field(default_factory=Contact)
# generated by datamodel-codegen:
#   filename:  default_factory_nested_model.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType, field


class Address(Struct):
    street: str | UnsetType = UNSET
    city: str | UnsetType = UNSET


class Contact(Struct):
    email: str | UnsetType = UNSET
    phone: str | UnsetType = UNSET


class Model(Struct):
    name: str
    address: Address | UnsetType = field(default_factory=Address)
    contact: Contact | UnsetType = field(default_factory=Contact)

--use-default-kwarg

Use default= keyword argument instead of positional argument for fields with defaults.

The --use-default-kwarg flag generates Field() declarations using default= as a keyword argument instead of a positional argument for fields that have default values.

Usage

datamodel-codegen --input annotated.graphql --use-default-kwarg # (1)!
  1. --use-default-kwarg - the option documented here
Examples

Input Schema:

type A {
    field: String!
    optionalField: String
    listField: [String!]!
    listOptionalField: [String]!
    optionalListField: [String!]
    optionalListOptionalField: [String]
    listListField:[[String!]!]!
}

Output:

# generated by datamodel-codegen:
#   filename:  annotated.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`.
"""


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 A(BaseModel):
    field: String
    listField: list[String]
    listListField: list[list[String]]
    listOptionalField: list[String | None]
    optionalField: String | None = None
    optionalListField: list[String] | None = None
    optionalListOptionalField: list[String | None] | None = None
    typename__: Literal['A'] | None = Field(default='A', alias='__typename')

--use-duplicate-name-suffix-for-every-collision

Give the --duplicate-name-suffix suffix to every model renamed in its module.

The parse names a model whose name another model already holds with the suffix of --duplicate-name-suffix. A model renamed later because its name is taken in its module, by an inline model of the same name or by a name the module imports (a definition AnyUrl beside a format: uri field), takes the suffix Model whatever the option says. With --use-duplicate-name-suffix-for-every-collision it takes the suffix the map gives its kind (model or enum, else default), and Model where the map gives none. Without --duplicate-name-suffix the option changes nothing.

Related: --duplicate-name-suffix

Usage

datamodel-codegen --input duplicate_name_suffix_every_collision.json --duplicate-name-suffix '{"model": "Schema", "enum": "Kind"}' --use-duplicate-name-suffix-for-every-collision # (1)!
  1. --use-duplicate-name-suffix-for-every-collision - the option documented here
Examples

Input Schema:

{
  "$defs": {
    "Item": {"type": "object", "properties": {"v": {"type": "string"}}},
    "AnyUrl": {"type": "object", "properties": {"href": {"type": "string"}}},
    "Status": {"type": "string", "enum": ["open", "closed"]}
  },
  "title": "Root",
  "type": "object",
  "properties": {
    "item": {"type": "object", "properties": {"w": {"type": "integer"}}},
    "other": {"$ref": "#/$defs/Item"},
    "site": {"type": "string", "format": "uri"},
    "link": {"$ref": "#/$defs/AnyUrl"},
    "status": {"type": "string", "enum": ["new", "old"]},
    "state": {"$ref": "#/$defs/Status"}
  }
}

Output:

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

from __future__ import annotations

from enum import Enum

from pydantic import AnyUrl, BaseModel


class Item(BaseModel):
    w: int | None = None


class Status(Enum):
    new = 'new'
    old = 'old'


class ItemSchema(BaseModel):
    v: str | None = None


class AnyUrlSchema(BaseModel):
    href: str | None = None


class StatusKind(Enum):
    open = 'open'
    closed = 'closed'


class Root(BaseModel):
    item: Item | None = None
    other: ItemSchema | None = None
    site: AnyUrl | None = None
    link: AnyUrlSchema | None = None
    status: Status | None = None
    state: StatusKind | None = None
# generated by datamodel-codegen:
#   filename:  duplicate_name_suffix_every_collision.json

from __future__ import annotations

from enum import Enum

from pydantic import AnyUrl, BaseModel


class Item(BaseModel):
    w: int | None = None


class Status(Enum):
    new = 'new'
    old = 'old'


class ItemModel(BaseModel):
    v: str | None = None


class AnyUrlModel(BaseModel):
    href: str | None = None


class StatusModel(Enum):
    open = 'open'
    closed = 'closed'


class Root(BaseModel):
    item: Item | None = None
    other: ItemModel | None = None
    site: AnyUrl | None = None
    link: AnyUrlModel | None = None
    status: Status | None = None
    state: StatusModel | None = None

--use-frozen-field

Generate frozen (immutable) field definitions for readOnly properties.

The --use-frozen-field flag generates frozen field definitions: - Pydantic v2: Field(frozen=True) - Dataclasses: silently ignored (no frozen fields generated)

Usage

datamodel-codegen --input use_frozen_field.json --use-frozen-field # (1)!
  1. --use-frozen-field - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object",
  "required": ["id", "name", "password"],
  "properties": {
    "id": {
      "type": "integer",
      "description": "Server-generated ID",
      "readOnly": true
    },
    "name": {
      "type": "string"
    },
    "password": {
      "type": "string",
      "description": "User password",
      "writeOnly": true
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "readOnly": true
    }
  }
}

Output:

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

from __future__ import annotations

from pydantic import AwareDatetime, BaseModel, Field


class User(BaseModel):
    id: int = Field(..., description='Server-generated ID', frozen=True)
    name: str
    password: str = Field(..., description='User password')
    created_at: AwareDatetime | None = Field(None, frozen=True)
# generated by datamodel-codegen:
#   filename:  use_frozen_field.json
#   timestamp: 2019-07-26T00:00:00+00:00

from __future__ import annotations

from dataclasses import dataclass


@dataclass
class User:
    id: int
    name: str
    password: str
    created_at: str | None = None

--use-generic-base-class

Generate a shared base class with model configuration to avoid repetition (DRY).

Usage

datamodel-codegen --input extra_fields.json --extra-fields forbid --output-model-type pydantic_v2.BaseModel --use-generic-base-class # (1)!
  1. --use-generic-base-class - the option documented here
Examples

Input Schema:

{
  "title": "Test",
  "type": "object",
  "required": [
    "foo"
  ],
  "properties": {
    "foo": {
      "type": "object",
      "properties": {
        "x": {
          "type": "integer"
        }
      },
      "additionalProperties": true
    },
    "bar": {
      "type": "object",
      "properties": {
        "y": {
          "type": "integer"
        }
      },
      "additionalProperties": false
    },
    "baz": {
      "type": "object",
      "properties": {
        "z": {
          "type": "integer"
        }
      }
    }
  },
  "additionalProperties": false
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel as _BaseModel
from pydantic import ConfigDict


class BaseModel(_BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )


class Foo(BaseModel):
    model_config = ConfigDict(
        extra='allow',
    )
    x: int | None = None


class Bar(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    y: int | None = None


class Baz(BaseModel):
    z: int | None = None


class Test(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    foo: Foo
    bar: Bar | None = None
    baz: Baz | None = None

--use-missing-sentinel

Use Pydantic's MISSING sentinel for unset optional BaseModel or dataclass fields.

The --use-missing-sentinel flag generates MISSING as the default for optional Pydantic v2 BaseModel or dataclass fields that do not define a schema default. This preserves the difference between an omitted field and a nullable field set to None.

Related: --strict-nullable, --target-pydantic-version

Option relationships:

Usage

datamodel-codegen --input missing_sentinel.json --output-model-type pydantic_v2.BaseModel --use-missing-sentinel # (1)!
  1. --use-missing-sentinel - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "MissingSentinel",
  "type": "object",
  "required": ["required", "requiredNullable"],
  "properties": {
    "required": {
      "type": "integer"
    },
    "requiredNullable": {
      "type": ["integer", "null"]
    },
    "unrequired": {
      "type": "integer"
    },
    "nullableUnrequired": {
      "type": ["integer", "null"]
    },
    "withDefault": {
      "type": "integer",
      "default": 1
    },
    "nullDefault": {
      "type": ["integer", "null"],
      "default": null
    },
    "aliased-field": {
      "type": "string"
    }
  }
}

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field
from pydantic.experimental.missing_sentinel import MISSING


class MissingSentinel(BaseModel):
    required: int
    requiredNullable: int | None
    unrequired: int | MISSING = MISSING
    nullableUnrequired: int | None | MISSING = MISSING
    withDefault: int | None = 1
    nullDefault: int | None = None
    aliased_field: str | MISSING = Field(MISSING, alias='aliased-field')

--use-msgspec-forbid-unknown-fields

Reject the unknown fields of a msgspec Struct whose schema admits no property but its own.

A schema with additionalProperties: false rejects every property its properties do not name, and Pydantic output writes extra='forbid' for it, but a msgspec.Struct ignores unknown fields, so it decodes payloads the schema rejects. With this option such a Struct is written with forbid_unknown_fields=True, also where an inline allOf member closes it with additionalProperties: false or unevaluatedProperties: false; a subclass inherits it. A schema with patternProperties beside additionalProperties: false admits the keys its patterns match, which msgspec cannot check, so its Struct stays open. --extra-fields forbid writes it on every Struct, as --use-generic-base-class does on the base class already, and --extra-fields allow or ignore and --allow-extra-fields keep every Struct open.

Usage

datamodel-codegen --input msgspec_forbid_unknown_fields.json --output-model-type msgspec.Struct --use-msgspec-forbid-unknown-fields # (1)!
  1. --use-msgspec-forbid-unknown-fields - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "Closed": {
      "type": "object",
      "properties": {"a": {"type": "string"}},
      "additionalProperties": false
    },
    "PatternKeys": {
      "type": "object",
      "properties": {"a": {"type": "string"}},
      "patternProperties": {"^x-": {"type": "string"}},
      "additionalProperties": false
    },
    "ClosedByMember": {
      "allOf": [
        {"type": "object", "properties": {"b": {"type": "string"}}, "additionalProperties": false}
      ]
    },
    "Child": {
      "allOf": [
        {"$ref": "#/$defs/Closed"},
        {"type": "object", "properties": {"c": {"type": "string"}}}
      ]
    },
    "Open": {
      "type": "object",
      "properties": {"d": {"type": "string"}}
    }
  },
  "type": "object",
  "properties": {
    "closed": {"$ref": "#/$defs/Closed"},
    "pattern_keys": {"$ref": "#/$defs/PatternKeys"},
    "by_member": {"$ref": "#/$defs/ClosedByMember"},
    "child": {"$ref": "#/$defs/Child"},
    "open": {"$ref": "#/$defs/Open"}
  },
  "additionalProperties": false
}

Output:

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

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType


class Closed(Struct, forbid_unknown_fields=True):
    a: str | UnsetType = UNSET


class PatternKeys(Struct):
    a: str | UnsetType = UNSET


class ClosedByMember(Struct, forbid_unknown_fields=True):
    b: str | UnsetType = UNSET


class Child(Closed):
    c: str | UnsetType = UNSET


class Open(Struct):
    d: str | UnsetType = UNSET


class Model(Struct, forbid_unknown_fields=True):
    closed: Closed | UnsetType = UNSET
    pattern_keys: PatternKeys | UnsetType = UNSET
    by_member: ClosedByMember | UnsetType = UNSET
    child: Child | UnsetType = UNSET
    open: Open | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  msgspec_forbid_unknown_fields.json

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType


class Closed(Struct):
    a: str | UnsetType = UNSET


class PatternKeys(Struct):
    a: str | UnsetType = UNSET


class ClosedByMember(Struct):
    b: str | UnsetType = UNSET


class Child(Closed):
    c: str | UnsetType = UNSET


class Open(Struct):
    d: str | UnsetType = UNSET


class Model(Struct):
    closed: Closed | UnsetType = UNSET
    pattern_keys: PatternKeys | UnsetType = UNSET
    by_member: ClosedByMember | UnsetType = UNSET
    child: Child | UnsetType = UNSET
    open: Open | UnsetType = UNSET

--use-msgspec-meta-for-map-keys

Check the keys of a msgspec map whose keys propertyNames or patternProperties constrain.

A map whose keys a propertyNames schema or the patterns of patternProperties constrain by pattern, minLength or maxLength is written with str keys in msgspec.Struct output, so every key decodes, while Pydantic output checks them. With this option the keys are Annotated[str, Meta(...)], which msgspec checks at decode. The keys of a propertyNames union stay str, as msgspec decodes a union of strings by one of them.

Usage

datamodel-codegen --input msgspec_map_keys.json --output-model-type msgspec.Struct --use-msgspec-meta-for-map-keys # (1)!
  1. --use-msgspec-meta-for-map-keys - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Model",
  "type": "object",
  "properties": {
    "named": {
      "type": "object",
      "propertyNames": {"pattern": "^[a-z]+$"},
      "additionalProperties": {"type": "string"}
    },
    "sized": {
      "type": "object",
      "propertyNames": {"minLength": 2, "maxLength": 4},
      "additionalProperties": {"type": "integer"}
    },
    "patterned": {
      "type": "object",
      "patternProperties": {"^x-": {"type": "string"}},
      "additionalProperties": false
    },
    "named_and_patterned": {
      "type": "object",
      "propertyNames": {"maxLength": 5},
      "patternProperties": {"^[a-z]+$": {"type": "string"}},
      "additionalProperties": false
    },
    "nested": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {"pattern": "^[0-9]+$"},
        "additionalProperties": {"type": "boolean"}
      }
    },
    "either": {
      "type": "object",
      "propertyNames": {"anyOf": [{"pattern": "^a"}, {"pattern": "^b"}]},
      "additionalProperties": {"type": "string"}
    },
    "single_branch": {
      "type": "object",
      "propertyNames": {"anyOf": [{"pattern": "^a"}]},
      "additionalProperties": {"type": "string"}
    }
  }
}

Output:

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

from __future__ import annotations

from typing import Annotated

from msgspec import UNSET, Meta, Struct, UnsetType


class Model(Struct):
    named: dict[Annotated[str, Meta(pattern='^[a-z]+$')], str] | UnsetType = UNSET
    sized: dict[Annotated[str, Meta(max_length=4, min_length=2)], int] | UnsetType = (
        UNSET
    )
    patterned: dict[Annotated[str, Meta(pattern='^x-')], str] | UnsetType = UNSET
    named_and_patterned: (
        dict[Annotated[str, Meta(max_length=5, pattern='^[a-z]+$')], str] | UnsetType
    ) = UNSET
    nested: list[dict[Annotated[str, Meta(pattern='^[0-9]+$')], bool]] | UnsetType = (
        UNSET
    )
    either: dict[str, str] | UnsetType = UNSET
    single_branch: dict[Annotated[str, Meta(pattern='^a')], str] | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  msgspec_map_keys.json

from __future__ import annotations

from msgspec import UNSET, Struct, UnsetType


class Model(Struct):
    named: dict[str, str] | UnsetType = UNSET
    sized: dict[str, int] | UnsetType = UNSET
    patterned: dict[str, str] | UnsetType = UNSET
    named_and_patterned: dict[str, str] | UnsetType = UNSET
    nested: list[dict[str, bool]] | UnsetType = UNSET
    either: dict[str, str] | UnsetType = UNSET
    single_branch: dict[str, str] | UnsetType = UNSET

--use-msgspec-nullable-enum-alias

Write a msgspec.Struct enum that lists null as an Enum and a nullable alias.

The --use-msgspec-nullable-enum-alias flag only applies to --output-model-type msgspec.Struct; other output model types ignore it. Client generation (--generate-client) with msgspec.Struct models requires it.

Without the flag the output keeps the 0.83.0 form of an enum that lists null without type: string or nullable: true, such as type: [integer, "null"] with enum: [1, 2, null]: an Enum class with a None member such as NoneType_None = None. msgspec cannot decode such an Enum, because its members must be all str or all int values. An enum whose class has a value type base, the IntEnum of type: integer or a --use-subclass-enum class such as (int, Enum), cannot hold a None member, so without the flag it is written without it, and without None as its one type rejects null.

With the flag the enum is written as a type: string or nullable enum is: an Enum class with an Enum suffix and without the None member, and the schema name becomes a type alias of that class or None, so that msgspec decodes the members and null. Code that used Size.int_1 or Size.NoneType_None uses SizeEnum.int_1 and None instead. The default of a field of the enum is then its raw value, also with --set-default-enum-member, and an enum that lists only null becomes the alias None.

Usage

datamodel-codegen --input msgspec_nullable_enum_31.yaml --use-msgspec-nullable-enum-alias --output-model-type msgspec.Struct # (1)!
  1. --use-msgspec-nullable-enum-alias - the option documented here
Examples

Input Schema:

openapi: 3.1.0
info: {title: Nullable enums, version: "1"}
paths: {}
components:
  schemas:
    Color:
      type: [string, "null"]
      enum: [red, green, null]
    Size:
      type: [integer, "null"]
      enum: [1, 2, null]
      default: 1
    Pet:
      type: object
      required: [name, color]
      properties:
        name: {type: string}
        color: {$ref: "#/components/schemas/Color"}
        size: {$ref: "#/components/schemas/Size"}
        sizes: {type: array, items: {$ref: "#/components/schemas/Size"}}

Output:

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

from __future__ import annotations

from enum import Enum
from typing import Annotated, TypeAlias

from msgspec import UNSET, Struct, UnsetType


class ColorEnum(Enum):
    red = 'red'
    green = 'green'


Color: TypeAlias = ColorEnum | None


class SizeEnum(Enum):
    int_1 = 1
    int_2 = 2


Size: TypeAlias = Annotated[SizeEnum | None, 1]


class Pet(Struct):
    name: str
    color: Color
    size: Size | UnsetType = 1
    sizes: list[Size] | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  msgspec_nullable_enum_31.yaml

from __future__ import annotations

from enum import Enum

from msgspec import UNSET, Struct, UnsetType


class Color(Enum):
    red = 'red'
    green = 'green'
    NoneType_None = None


class Size(Enum):
    int_1 = 1
    int_2 = 2
    NoneType_None = None


class Pet(Struct):
    name: str
    color: Color
    size: Size | UnsetType = 1
    sizes: list[Size] | UnsetType = UNSET

--use-msgspec-tagged-unions

Write a msgspec.Struct discriminated union as tagged structs as a whole.

The --use-msgspec-tagged-unions flag only applies to --output-model-type msgspec.Struct; other output model types ignore it. Client generation (--generate-client) with msgspec.Struct models requires it.

Without the flag the output keeps the 0.83.0 form. A variant gets tag_field/tag only when its discriminator property is a single literal (such as a const) equal to the discriminator value, or when a second discriminated union uses the variant, and such a tag names the generated field, which differs from the property name when the field is renamed. Any other variant, whose value comes from the discriminator mapping, an enum or the schema name, keeps the discriminator as a Literal field: Cat(petType='cat') and cat.petType work and Cat decodes alone, but msgspec raises TypeError for the union Cat | Dog, because it only decodes unions of tagged structs.

With the flag a union is tagged as a whole: every variant gets the property name of the document as tag_field and its value as tag, so the union decodes. msgspec does not allow a field named like tag_field, so the discriminator is then neither a field nor a constructor argument: Cat(petType='cat') raises TypeError, cat.petType raises AttributeError, and Cat decoded alone accepts a payload without petType.

When a variant cannot take exactly one tag for the union, or a base or derived struct of a variant keeps the property as a field, the union tags none of its variants and a warning names the reason: its variants keep Literal fields, the ones with a const included. A variant that another union tags keeps that tag.

Usage

datamodel-codegen --input direct.json --use-msgspec-tagged-unions --output-model-type msgspec.Struct # (1)!
  1. --use-msgspec-tagged-unions - the option documented here
Examples

Input Schema:

{
  "openapi": "3.0.3",
  "info": {
    "title": "Discriminator field aliases",
    "version": "1"
  },
  "paths": {},
  "components": {
    "schemas": {
      "Cat": {
        "type": "object",
        "properties": {
          "petType": {
            "type": "string",
            "enum": [
              "cat"
            ]
          },
          "meow": {
            "type": "string"
          }
        },
        "required": [
          "petType"
        ]
      },
      "Dog": {
        "type": "object",
        "properties": {
          "petType": {
            "type": "string",
            "enum": [
              "dog"
            ]
          },
          "bark": {
            "type": "string"
          }
        },
        "required": [
          "petType"
        ]
      },
      "Pet": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/Cat"
          },
          {
            "$ref": "#/components/schemas/Dog"
          }
        ],
        "discriminator": {
          "propertyName": "petType",
          "mapping": {
            "cat": "#/components/schemas/Cat",
            "dog": "#/components/schemas/Dog"
          }
        }
      },
      "Unrelated": {
        "type": "object",
        "properties": {
          "petType": {
            "type": "string"
          }
        }
      }
    }
  }
}

Output:

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

from __future__ import annotations

from enum import Enum
from typing import TypeAlias

from msgspec import UNSET, Struct, UnsetType


class PetType(Enum):
    cat = 'cat'


class Cat(Struct, tag_field='petType', tag='cat'):
    meow: str | UnsetType = UNSET


class PetType1(Enum):
    dog = 'dog'


class Dog(Struct, tag_field='petType', tag='dog'):
    bark: str | UnsetType = UNSET


Pet: TypeAlias = Cat | Dog


class Unrelated(Struct):
    petType: str | UnsetType = UNSET
# generated by datamodel-codegen:
#   filename:  direct.json

from __future__ import annotations

from enum import Enum
from typing import Literal, TypeAlias

from msgspec import UNSET, Struct, UnsetType


class PetType(Enum):
    cat = 'cat'


class Cat(Struct):
    petType: Literal['cat']
    meow: str | UnsetType = UNSET


class PetType1(Enum):
    dog = 'dog'


class Dog(Struct):
    petType: Literal['dog']
    bark: str | UnsetType = UNSET


Pet: TypeAlias = Cat | Dog


class Unrelated(Struct):
    petType: str | UnsetType = UNSET

--use-one-literal-as-default

Use single literal value as default when enum has only one option.

The --use-one-literal-as-default flag configures the code generation behavior.

Usage

datamodel-codegen --input enum_models.yaml --use-one-literal-as-default --enum-field-as-literal one # (1)!
  1. --use-one-literal-as-default - 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
components:
  schemas:
    Pet:
      required:
        - id
        - name
        - number
        - boolean
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
        kind:
          type: string
          enum: ['dog', 'cat']
        type:
          type: string
          enum: [ 'animal' ]
        number:
          type: integer
          enum: [ 1 ]
        boolean:
          type: boolean
          enum: [ true ]

    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    animal:
      type: object
      properties:
        kind:
          type: string
          enum: ['snake', 'rabbit']
    Error:
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
    EnumObject:
      type: object
      properties:
        type:
          enum: ['a', 'b']
          type: string
    EnumRoot:
      enum: ['a', 'b']
      type: string
    IntEnum:
      enum: [1,2]
      type: number
    AliasEnum:
      enum: [1,2,3]
      type: number
      x-enum-varnames: ['a', 'b', 'c']
    MultipleTypeEnum:
      enum: [ "red", "amber", "green", null, 42 ]
    singleEnum:
      enum: [ "pet" ]
      type: string
    arrayEnum:
      type: array
      items: [
        { enum: [ "cat" ] },
        { enum: [ "dog"]}
      ]
    nestedNullableEnum:
      type: object
      properties:
        nested_version:
          type: string
          nullable: true
          default: RC1
          description: nullable enum
          example: RC2
          enum:
            - RC1
            - RC1N
            - RC2
            - RC2N
            - RC3
            - RC4
            - null
    version:
      type: string
      nullable: true
      default: RC1
      description: nullable enum
      example: RC2
      enum:
      - RC1
      - RC1N
      - RC2
      - RC2N
      - RC3
      - RC4
      - null

Output:

# generated by datamodel-codegen:
#   filename:  enum_models.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 Kind(Enum):
    dog = 'dog'
    cat = 'cat'


class Pet(BaseModel):
    id: int
    name: str
    tag: str | None = None
    kind: Kind | None = None
    type: Literal['animal'] | None = None
    number: Literal[1] = 1
    boolean: Literal[True] = True


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


class Kind1(Enum):
    snake = 'snake'
    rabbit = 'rabbit'


class Animal(BaseModel):
    kind: Kind1 | None = None


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


class Type(Enum):
    a = 'a'
    b = 'b'


class EnumObject(BaseModel):
    type: Type | None = None


class EnumRoot(Enum):
    a = 'a'
    b = 'b'


class IntEnum(Enum):
    number_1 = 1
    number_2 = 2


class AliasEnum(Enum):
    a = 1
    b = 2
    c = 3


class MultipleTypeEnum(Enum):
    red = 'red'
    amber = 'amber'
    green = 'green'
    NoneType_None = None
    int_42 = 42


class SingleEnum(RootModel[Literal['pet']]):
    root: Literal['pet'] = 'pet'


class ArrayEnum(RootModel[list[Literal['cat'] | Literal['dog']]]):
    root: list[Literal['cat'] | Literal['dog']]


class NestedVersionEnum(Enum):
    RC1 = 'RC1'
    RC1N = 'RC1N'
    RC2 = 'RC2'
    RC2N = 'RC2N'
    RC3 = 'RC3'
    RC4 = 'RC4'


class NestedVersion(RootModel[NestedVersionEnum | None]):
    root: NestedVersionEnum | None = Field(
        'RC1', description='nullable enum', examples=['RC2']
    )


class NestedNullableEnum(BaseModel):
    nested_version: NestedVersion | None = Field(
        'RC1', description='nullable enum', examples=['RC2'], validate_default=True
    )


class VersionEnum(Enum):
    RC1 = 'RC1'
    RC1N = 'RC1N'
    RC2 = 'RC2'
    RC2N = 'RC2N'
    RC3 = 'RC3'
    RC4 = 'RC4'


class Version(RootModel[VersionEnum | None]):
    root: VersionEnum | None = Field(
        'RC1', description='nullable enum', examples=['RC2']
    )

--use-root-model-sequence-interface

Make non-null sequence-like Pydantic v2 RootModel classes implement collections.abc.Sequence.

When enabled, a RootModel whose root is list[T] or Sequence[T] inherits from Sequence[T] and includes iter, getitem, and len methods that delegate to the wrapped root value. Scalar, optional, nullable, and RootModel type-alias outputs are unchanged.

This makes generated RootModel wrappers convenient to use anywhere a typed sequence is expected, without unpacking .root at every call site:

from collections.abc import Sequence

pets = Pets(root=[Pet(name="dog")])

first_pet: Pet = pets[0]
selected_pets: list[Pet] = pets[:1]
pet_names = [pet.name for pet in pets]


def render_pet_names(pets: Sequence[Pet]) -> list[str]:
    return [pet.name for pet in pets]


render_pet_names(pets)

When used with --custom-template-dir, a custom pydantic_v2/RootModel.jinja2 template must render both sequence_base_class and the helper methods using sequence_item_type and sequence_slice_type. If the custom RootModel template does not render the sequence base class and helper methods, generation fails with an error instead of silently ignoring this option.

Usage

datamodel-codegen --input root_model_sequence_interface.json --output-model-type pydantic_v2.BaseModel --use-root-model-sequence-interface --class-name Pets # (1)!
  1. --use-root-model-sequence-interface - the option documented here
Examples

Input Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "items": {
    "$ref": "#/definitions/Pet"
  },
  "definitions": {
    "Pet": {
      "type": "object",
      "required": [
        "name"
      ],
      "properties": {
        "name": {
          "type": "string"
        }
      }
    }
  }
}

Output:

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

from __future__ import annotations

from collections.abc import Iterator, Sequence
from typing import SupportsIndex, overload

from pydantic import BaseModel, RootModel


class Pet(BaseModel):
    name: str


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

    def __iter__(self) -> Iterator[Pet]:
        return iter(self.root)

    @overload
    def __getitem__(self, index: SupportsIndex) -> Pet:
        pass

    @overload
    def __getitem__(self, index: slice) -> list[Pet]:
        pass

    def __getitem__(self, index: SupportsIndex | slice) -> Pet | list[Pet]:
        return self.root[index]

    def __len__(self) -> int:
        return len(self.root)

--use-serialize-as-any

Wrap fields with subtypes in Pydantic's SerializeAsAny.

The --use-serialize-as-any flag applies Pydantic v2's SerializeAsAny wrapper to fields that have subtype relationships, ensuring proper serialization of polymorphic types and inheritance hierarchies.

Usage

datamodel-codegen --input serialize_as_any.yaml --use-serialize-as-any # (1)!
  1. --use-serialize-as-any - the option documented here
Examples

Input Schema:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: SerializeAsAny Test
  description: Test schema for SerializeAsAny annotation on types with subtypes
paths: {}
components:
  schemas:
    User:
      type: object
      description: Base user model
      properties:
        name:
          type: string
          description: User's name
      required:
        - name

    AdminUser:
      allOf:
        - $ref: '#/components/schemas/User'
        - type: object
          description: Admin user with additional permissions
          properties:
            admin_level:
              type: integer
              description: Admin permission level
          required:
            - admin_level

    Container:
      type: object
      description: Container that holds user references
      properties:
        admin_user_field:
          $ref: '#/components/schemas/AdminUser'
          description: Field that should not use SerializeAsAny
        user_field:
          $ref: '#/components/schemas/User'
          description: Field that should use SerializeAsAny
        user_list:
          type: array
          description: List of users that should use SerializeAsAny
          items:
            $ref: '#/components/schemas/User'
      required:
        - user_field
        - user_list
        - admin_user_field

Output:

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

from __future__ import annotations

from pydantic import BaseModel, Field, SerializeAsAny


class User(BaseModel):
    name: str = Field(..., description="User's name")


class AdminUser(User):
    admin_level: int = Field(..., description='Admin permission level')


class Container(BaseModel):
    admin_user_field: AdminUser = Field(
        ..., description='Field that should not use SerializeAsAny'
    )
    user_field: SerializeAsAny[User] = Field(
        ..., description='Field that should use SerializeAsAny'
    )
    user_list: list[SerializeAsAny[User]] = Field(
        ..., description='List of users that should use SerializeAsAny'
    )

--use-serialize-as-any-for-every-subclass

Wrap a field in SerializeAsAny when any subclass of its model adds fields.

--use-serialize-as-any wraps a field whose model has a direct subclass that adds fields, as the subclasses recorded when the model was parsed tell, so a subclass two levels down, a subclass of a model that --reuse-model or --collapse-reuse-models merged into another, and a field that names its model through its module (c.Base) are left out and serialize as the base model. With this option the class hierarchy of the generated output decides: a field is wrapped when any subclass of its model, at any depth, adds fields (Pydantic v2 only).

Usage

datamodel-codegen --input serialize_as_any_every_subclass.json --use-serialize-as-any --use-serialize-as-any-for-every-subclass --reuse-model # (1)!
  1. --use-serialize-as-any-for-every-subclass - the option documented here
Examples

Input Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "A": {"type": "object", "properties": {"x": {"type": "string"}}},
    "B": {"type": "object", "properties": {"x": {"type": "string"}}},
    "Sub": {"allOf": [{"$ref": "#/$defs/B"}, {"type": "object", "properties": {"y": {"type": "integer"}}}]},
    "C": {"type": "object", "properties": {"z": {"type": "string"}}},
    "Mid": {"allOf": [{"$ref": "#/$defs/C"}]},
    "Leaf": {"allOf": [{"$ref": "#/$defs/Mid"}, {"type": "object", "properties": {"w": {"type": "integer"}}}]},
    "Holder": {
      "type": "object",
      "properties": {"a": {"$ref": "#/$defs/A"}, "b": {"$ref": "#/$defs/B"}, "c": {"$ref": "#/$defs/C"}}
    }
  }
}

Output:

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

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, RootModel, SerializeAsAny


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


class A(BaseModel):
    x: str | None = None


class B(A):
    pass


class Sub(B):
    y: int | None = None


class C(BaseModel):
    z: str | None = None


class Mid(C):
    pass


class Leaf(Mid):
    w: int | None = None


class Holder(BaseModel):
    a: SerializeAsAny[A] | None = None
    b: SerializeAsAny[B] | None = None
    c: SerializeAsAny[C] | None = None
# generated by datamodel-codegen:
#   filename:  serialize_as_any_every_subclass.json

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, RootModel


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


class A(BaseModel):
    x: str | None = None


class B(A):
    pass


class Sub(B):
    y: int | None = None


class C(BaseModel):
    z: str | None = None


class Mid(C):
    pass


class Leaf(Mid):
    w: int | None = None


class Holder(BaseModel):
    a: A | None = None
    b: B | None = None
    c: C | None = None

--use-subclass-enum

Generate typed Enum subclasses for enums with specific field types.

The --use-subclass-enum flag generates Enum classes as subclasses of the appropriate field type (int, float, bytes, str) when an enum has a specific type, providing better type safety and IDE support.

Usage

datamodel-codegen --input enums.graphql --use-subclass-enum # (1)!
  1. --use-subclass-enum - the option documented here
Examples

Input Schema:

"Employee shift status"
enum EmployeeShiftStatus {
  "not on shift"
  NOT_ON_SHIFT
  "on shift"
  ON_SHIFT
}

enum Color {
  RED
  GREEN
  BLUE
}

enum EnumWithOneField {
    FIELD
}

Output:

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

from __future__ import annotations

from enum import Enum

from typing_extensions import TypeAliasType

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


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 Color(str, Enum):
    BLUE = 'BLUE'
    GREEN = 'GREEN'
    RED = 'RED'


class EmployeeShiftStatus(str, Enum):
    """
    Employee shift status
    """

    NOT_ON_SHIFT = 'NOT_ON_SHIFT'
    ON_SHIFT = 'ON_SHIFT'


class EnumWithOneField(str, Enum):
    FIELD = 'FIELD'