🏗️ 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)!
-
--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:
- Implies:
--extra-fields=allow
Usage
-
--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)!
-
--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
-
--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)!
-
--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
-
--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)!
-
--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
-
--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)!
-
--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
-
--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
-
--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)!
-
--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
-
--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
-
--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, RootModel
class ApiVersion(RootModel[Literal['v1']]):
root: Literal['v1'] = Field(..., description='The version of this API')
class Api(BaseModel):
version: ApiVersion
--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-modelsenabled ---collapse-root-models-name-strategyrequires--collapse-root-models.
Usage
datamodel-codegen --input collapse_root_models_name_strategy_child.json --collapse-root-models --collapse-root-models-name-strategy child # (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:
--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)!
-
--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, 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)!
-
--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
-
--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
-
--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
-
--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)!
-
--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:
--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)!
-
--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)!
-
--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)!
-
--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)!
-
--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]
--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)!
-
--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
-
--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)!
-
--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)!
-
--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)!
-
--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)!
-
--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-onlyrequires--target-python-version3.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)!
-
--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
-
--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
-
--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)!
-
--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)!
-
--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
-
--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
-
--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
-
--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)!
-
--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)!
-
--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-annotatedenabled
Usage
-
--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:
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:
- Implies:
--naming-strategy=parent-prefixed
Usage
datamodel-codegen --input duplicate_models2.yaml --parent-scoped-naming --use-operation-id-as-name --openapi-scopes paths schemas parameters # (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)!
-
--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)!
-
--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)!
-
--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
-
--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-modelenabled ---reuse-scope=treehas no effect without--reuse-model.
Usage
-
--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)!
-
--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)!
-
--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:
--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
-
--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
-
--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)!
-
--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 keepspopulate_by_name=Truelike2, and--use-missing-sentinelkeeps the experimentalMISSINGimport - 2: Pydantic 2.0.3+ compatible forms, such as
populate_by_name=True,Field(...)string constraints,json_schema_extrafor deprecated fields, and dictionary-key models defined first - 2.11: Pydantic 2.11+ forms, such as
validate_by_name=True,StringConstraints,Field(deprecated=True), andTypeAliasTypedataclass 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-sentinelimportingMISSINGfrompydanticinstead of thepydantic.experimental.missing_sentinelpath that Pydantic 2.14 deprecates, Python's regex engine forbytespatterns the Rust engine rejects, which Pydantic compiles from 2.14 on, and requiredpydantic_v2.dataclassfields written as= Field(...)placed before the fields with defaults of the same class, the orderinspect.signatureneeds 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)!
-
--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 | Noneunion operator,TypeAliasannotation - Python 3.12+: Uses
typestatement for type aliases - Python 3.13+: Imports
ReadOnlyfor read-only TypedDict keys fromtyping - Python 3.14+: Native deferred annotations;
from __future__ import annotationsonly when needed - Python 3.15+: Imports
TypedDictwithclosedandextra_items(PEP 728) fromtyping
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)!
-
--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-modeis 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)!
-
--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)!
-
--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)!
-
--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
-
--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)!
-
--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
-
--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)
--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)!
-
--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:
- Implies:
--target-pydantic-version=2.12 - Requires:
--output-model-type---use-missing-sentinelis only supported for--output-model-type pydantic_v2.BaseModelorpydantic_v2.dataclass.
Usage
datamodel-codegen --input missing_sentinel.json --output-model-type pydantic_v2.BaseModel --use-missing-sentinel # (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)!
-
--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)!
-
--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)!
-
--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)!
-
--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)!
-
--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)!
-
--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
-
--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)!
-
--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
-
--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'