From 94afac7040812b41e6ffce04e91c3269bf299a53 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 3 Jan 2026 06:23:56 +0000 Subject: [PATCH 1/5] Add llms.txt generator for LLM-friendly documentation --- .github/workflows/llms-txt.yaml | 72 + docs/llms-full.txt | 29884 ++++++++++++++++++++++++++++++ docs/llms.txt | 73 + pyproject.toml | 2 +- scripts/build_llms_txt.py | 390 + tox.ini | 7 + 6 files changed, 30427 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/llms-txt.yaml create mode 100644 docs/llms-full.txt create mode 100644 docs/llms.txt create mode 100644 scripts/build_llms_txt.py diff --git a/.github/workflows/llms-txt.yaml b/.github/workflows/llms-txt.yaml new file mode 100644 index 000000000..ee1f86af2 --- /dev/null +++ b/.github/workflows/llms-txt.yaml @@ -0,0 +1,72 @@ +name: Update llms.txt + +on: + push: + branches: [main] + paths: + - 'docs/**/*.md' + - 'zensical.toml' + - 'scripts/build_llms_txt.py' + pull_request: + branches: [main] + paths: + - 'docs/**/*.md' + - 'zensical.toml' + - 'scripts/build_llms_txt.py' + pull_request_target: + types: [labeled] + paths: + - 'docs/**/*.md' + - 'zensical.toml' + - 'scripts/build_llms_txt.py' + +permissions: + contents: write + +jobs: + update-llms-txt: + if: | + github.event_name == 'push' || + !github.event.pull_request.head.repo.fork || + github.actor == 'koxudaxi' || + github.actor == 'gaborbernat' || + github.actor == 'ilovelinux' || + (github.event_name == 'pull_request_target' && github.event.label.name == 'safe-to-fix' && + (github.event.sender.login == 'koxudaxi' || + github.event.sender.login == 'gaborbernat' || + github.event.sender.login == 'ilovelinux')) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + - uses: actions/checkout@v4 + if: github.event_name == 'push' || github.event_name == 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.ref || github.ref }} + repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + token: ${{ secrets.PAT }} + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v5 + - name: Install tox + run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv + - name: Setup environment + run: tox run -vv --notest --skip-missing-interpreters false -e llms-txt + env: + UV_PYTHON_PREFERENCE: "only-managed" + - name: Build llms.txt + run: .tox/llms-txt/bin/python scripts/build_llms_txt.py + - name: Commit and push if changed + if: github.event_name == 'push' || github.event_name == 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add docs/llms.txt docs/llms-full.txt + git diff --staged --quiet || git commit -m "docs: update llms.txt files + + Generated by GitHub Actions" + git push diff --git a/docs/llms-full.txt b/docs/llms-full.txt new file mode 100644 index 000000000..b76df6144 --- /dev/null +++ b/docs/llms-full.txt @@ -0,0 +1,29884 @@ +# datamodel-code-generator + +Source: https://datamodel-code-generator.koxudaxi.dev/ + +๐Ÿš€ Generate Python data models from schema definitions in seconds. + +[![PyPI version](https://badge.fury.io/py/datamodel-code-generator.svg)](https://pypi.python.org/pypi/datamodel-code-generator) +[![Conda-forge](https://img.shields.io/conda/v/conda-forge/datamodel-code-generator)](https://anaconda.org/conda-forge/datamodel-code-generator) +[![Downloads](https://pepy.tech/badge/datamodel-code-generator/month)](https://pepy.tech/project/datamodel-code-generator) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/datamodel-code-generator)](https://pypi.python.org/pypi/datamodel-code-generator) +[![codecov](https://codecov.io/gh/koxudaxi/datamodel-code-generator/graph/badge.svg?token=plzSSFb9Li)](https://codecov.io/gh/koxudaxi/datamodel-code-generator) +![license](https://img.shields.io/github/license/koxudaxi/datamodel-code-generator.svg) +[![Pydantic v1](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v1.json)](https://pydantic.dev) +[![Pydantic v2](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json)](https://pydantic.dev) + +--- + +## โœจ What it does + +- ๐Ÿ“„ Converts **OpenAPI 3**, **JSON Schema**, **GraphQL**, and raw data (JSON/YAML/CSV) into Python models +- ๐Ÿ Generates from **existing Python types** (Pydantic, dataclass, TypedDict) via `--input-model` +- ๐ŸŽฏ Generates **Pydantic v1/v2**, **dataclasses**, **TypedDict**, or **msgspec** output +- ๐Ÿ”— Handles complex schemas: `$ref`, `allOf`, `oneOf`, `anyOf`, enums, and nested types +- โœ… Produces type-safe, validated code ready for your IDE and type checker + +--- + +## ๐Ÿ“ฆ Installation + +=== "uv tool (Recommended)" + + ```bash + uv tool install datamodel-code-generator + ``` + +=== "pip" + + ```bash + pip install datamodel-code-generator + ``` + +=== "uv (project)" + + ```bash + uv add datamodel-code-generator + ``` + +=== "conda" + + ```bash + conda install -c conda-forge datamodel-code-generator + ``` + +=== "pipx" + + ```bash + pipx install datamodel-code-generator + ``` + +=== "uvx (one-shot)" + + ```bash + uvx datamodel-codegen --help + ``` + +--- + +## ๐Ÿƒ Quick Start + +### 1๏ธโƒฃ Create a schema file + +```json title="pet.json" +--8<-- "tests/data/jsonschema/tutorial_pet.json" +``` + +### 2๏ธโƒฃ Run the generator + +```bash +datamodel-codegen --input pet.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --output model.py +``` + +### 3๏ธโƒฃ Use your models + +```python title="model.py" +--8<-- "tests/data/expected/main/jsonschema/tutorial_pet_v2.py" +``` + +๐ŸŽ‰ That's it! Your schema is now a fully-typed Python model. + +--- + +## ๐Ÿ“ฅ Choose Your Input + +| Input Type | File Types | Example | +|------------|------------|---------| +| ๐Ÿ“˜ [OpenAPI 3](openapi.md) | `.yaml`, `.json` | API specifications | +| ๐Ÿ“‹ [JSON Schema](jsonschema.md) | `.json` | Data validation schemas | +| ๐Ÿ”ท [GraphQL](graphql.md) | `.graphql` | GraphQL type definitions | +| ๐Ÿ“Š [JSON/YAML Data](jsondata.md) | `.json`, `.yaml` | Infer schema from data | +| ๐Ÿ [Python Models](python-model.md) | `.py` | Pydantic, dataclass, TypedDict | + +--- + +## ๐Ÿ“ค Choose Your Output + +```bash +# ๐Ÿ†• Pydantic v2 (recommended for new projects) +datamodel-codegen --output-model-type pydantic_v2.BaseModel ... + +# ๐Ÿ”„ Pydantic v1 (default, for compatibility) +datamodel-codegen --output-model-type pydantic.BaseModel ... + +# ๐Ÿ—๏ธ Python dataclasses +datamodel-codegen --output-model-type dataclasses.dataclass ... + +# ๐Ÿ“ TypedDict (for type hints without validation) +datamodel-codegen --output-model-type typing.TypedDict ... + +# โšก msgspec (high-performance serialization) +datamodel-codegen --output-model-type msgspec.Struct ... +``` + +See [Supported Data Types](supported-data-types.md) for the full list. + +--- + +## ๐Ÿณ Common Recipes + +### ๐Ÿค– Get CLI Help from LLMs + +Generate a prompt to ask LLMs about CLI options: + +```bash +datamodel-codegen --generate-prompt "Best options for Pydantic v2?" | claude -p +``` + +See [LLM Integration](llm-integration.md) for more examples. + +### ๐ŸŒ Generate from URL {#http-extra-option} + +```bash +pip install 'datamodel-code-generator[http]' +datamodel-codegen --url https://example.com/api/openapi.yaml --output model.py +``` + +### โš™๏ธ Use with pyproject.toml + +```toml title="pyproject.toml" +[tool.datamodel-codegen] +input = "schema.yaml" +output = "src/models.py" +output-model-type = "pydantic_v2.BaseModel" +``` + +Then simply run: + +```bash +datamodel-codegen +``` + +See [pyproject.toml Configuration](pyproject_toml.md) for more options. + +### ๐Ÿ”„ CI/CD Integration + +Validate generated models in your CI pipeline: + +```yaml title=".github/workflows/validate-models.yml" +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schemas/api.yaml + output: src/models/api.py +``` + +See [CI/CD Integration](ci-cd.md) for more options. + +--- + +## ๐Ÿ“š Next Steps + +- ๐Ÿ–ฅ๏ธ **[CLI Reference](cli-reference/index.md)** - All command-line options with examples +- โš™๏ธ **[pyproject.toml Configuration](pyproject_toml.md)** - Configure via pyproject.toml +- ๐Ÿš€ **[One-liner Usage](oneliner.md)** - uvx, pipx, clipboard integration +- ๐Ÿ”„ **[CI/CD Integration](ci-cd.md)** - GitHub Actions and CI validation +- ๐ŸŽจ **[Custom Templates](custom_template.md)** - Customize generated code with Jinja2 +- ๐Ÿ–Œ๏ธ **[Code Formatting](formatting.md)** - Configure black, isort, and ruff +- โ“ **[FAQ](faq.md)** - Common questions and troubleshooting + +--- + +## ๐Ÿ’– Sponsors + + + + + +
+ + Astral Logo +

Astral

+
+
+ +--- + +## ๐Ÿข Used by + +These projects use datamodel-code-generator. See the linked examples for real-world usage. + +- [PostHog/posthog](https://github.com/PostHog/posthog) - *[Generate models via npm run](https://github.com/PostHog/posthog/blob/e1a55b9cb38d01225224bebf8f0c1e28faa22399/package.json#L41)* +- [airbytehq/airbyte](https://github.com/airbytehq/airbyte) - *[Generate Python, Java/Kotlin, and Typescript protocol models](https://github.com/airbytehq/airbyte-protocol/tree/main/protocol-models/bin)* +- [apache/iceberg](https://github.com/apache/iceberg) - *[Generate Python code](https://github.com/apache/iceberg/blob/d2e1094ee0cc6239d43f63ba5114272f59d605d2/open-api/README.md?plain=1#L39)* +- [open-metadata/OpenMetadata](https://github.com/open-metadata/OpenMetadata) - *[datamodel_generation.py](https://github.com/open-metadata/OpenMetadata/blob/main/scripts/datamodel_generation.py)* +- [awslabs/aws-lambda-powertools-python](https://github.com/awslabs/aws-lambda-powertools-python) - *[Recommended for advanced-use-cases](https://awslabs.github.io/aws-lambda-powertools-python/2.6.0/utilities/parser/#advanced-use-cases)* +- [Netflix/consoleme](https://github.com/Netflix/consoleme) - *[Generate models from Swagger](https://github.com/Netflix/consoleme/blob/master/docs/gitbook/faq.md#how-do-i-generate-models-from-the-swagger-specification)* +- [DataDog/integrations-core](https://github.com/DataDog/integrations-core) - *[Config models](https://github.com/DataDog/integrations-core/blob/master/docs/developer/meta/config-models.md)* +- [argoproj-labs/hera](https://github.com/argoproj-labs/hera) - *[Makefile](https://github.com/argoproj-labs/hera/blob/c8cbf0c7a676de57469ca3d6aeacde7a5e84f8b7/Makefile#L53-L62)* +- [SeldonIO/MLServer](https://github.com/SeldonIO/MLServer) - *[generate-types.sh](https://github.com/SeldonIO/MLServer/blob/master/hack/generate-types.sh)* +- [geojupyter/jupytergis](https://github.com/geojupyter/jupytergis) - *[Python type generation from JSONSchema](https://jupytergis.readthedocs.io/en/latest/contributor_guide/explanation/code-generation.html)* +- [Nike-Inc/brickflow](https://github.com/Nike-Inc/brickflow) - *[Code generate tools](https://github.com/Nike-Inc/brickflow/blob/e3245bf638588867b831820a6675ada76b2010bf/tools/README.md?plain=1#L8)* +- [cloudcoil/cloudcoil](https://github.com/cloudcoil/cloudcoil) - *[Model generation](https://github.com/cloudcoil/cloudcoil#%EF%B8%8F-model-generation)* +- [IBM/compliance-trestle](https://github.com/IBM/compliance-trestle) - *[Building models from OSCAL schemas](https://github.com/IBM/compliance-trestle/blob/develop/docs/contributing/website.md#building-the-models-from-the-oscal-schemas)* +- [hashintel/hash](https://github.com/hashintel/hash) - *[codegen.sh](https://github.com/hashintel/hash/blob/9762b1a1937e14f6b387677e4c7fe4a5f3d4a1e1/libs/%40local/hash-graph-client/python/scripts/codegen.sh#L21-L39)* + +[See all dependents โ†’](https://github.com/koxudaxi/datamodel-code-generator/network/dependents) + +--- + +# CLI Reference + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/ + +This documentation is auto-generated from test cases. + +๐Ÿ” **[Quick Reference](quick-reference.md)** - All options on one page for Ctrl+F search + +## ๐Ÿ“‚ Categories + +| Category | Options | Description | +|----------|---------|-------------| +| ๐Ÿ“ [Base Options](base-options.md) | 7 | Input/output configuration | +| ๐Ÿ”ง [Typing Customization](typing-customization.md) | 27 | Type annotation and import behavior | +| ๐Ÿท๏ธ [Field Customization](field-customization.md) | 24 | Field naming and docstring behavior | +| ๐Ÿ—๏ธ [Model Customization](model-customization.md) | 39 | Model generation behavior | +| ๐ŸŽจ [Template Customization](template-customization.md) | 19 | Output formatting and custom rendering | +| ๐Ÿ“˜ [OpenAPI-only Options](openapi-only-options.md) | 7 | OpenAPI-specific features | +| ๐Ÿ“‹ [GraphQL-only Options](graphql-only-options.md) | 1 | | +| โš™๏ธ [General Options](general-options.md) | 15 | Utilities and meta options | +| ๐Ÿ“ [Utility Options](utility-options.md) | 6 | Help, version, debug options | + +## All Options + +**Jump to:** [A](#a) ยท [B](#b) ยท [C](#c) ยท [D](#d) ยท [E](#e) ยท [F](#f) ยท [G](#g) ยท [H](#h) ยท [I](#i) ยท [K](#k) ยท [M](#m) ยท [N](#n) ยท [O](#o) ยท [P](#p) ยท [R](#r) ยท [S](#s) ยท [T](#t) ยท [U](#u) ยท [V](#v) ยท [W](#w) + + +### A {#a} + +- [`--additional-imports`](template-customization.md#additional-imports) +- [`--aliases`](field-customization.md#aliases) +- [`--all-exports-collision-strategy`](general-options.md#all-exports-collision-strategy) +- [`--all-exports-scope`](general-options.md#all-exports-scope) +- [`--allof-class-hierarchy`](typing-customization.md#allof-class-hierarchy) +- [`--allof-merge-mode`](typing-customization.md#allof-merge-mode) +- [`--allow-extra-fields`](model-customization.md#allow-extra-fields) +- [`--allow-population-by-field-name`](model-customization.md#allow-population-by-field-name) + +### B {#b} + +- [`--base-class`](model-customization.md#base-class) +- [`--base-class-map`](model-customization.md#base-class-map) + +### C {#c} + +- [`--capitalize-enum-members`](field-customization.md#capitalize-enum-members) +- [`--check`](general-options.md#check) +- [`--class-decorators`](template-customization.md#class-decorators) +- [`--class-name`](model-customization.md#class-name) +- [`--class-name-affix-scope`](model-customization.md#class-name-affix-scope) +- [`--class-name-prefix`](model-customization.md#class-name-prefix) +- [`--class-name-suffix`](model-customization.md#class-name-suffix) +- [`--collapse-reuse-models`](model-customization.md#collapse-reuse-models) +- [`--collapse-root-models`](model-customization.md#collapse-root-models) +- [`--collapse-root-models-name-strategy`](model-customization.md#collapse-root-models-name-strategy) +- [`--custom-file-header`](template-customization.md#custom-file-header) +- [`--custom-file-header-path`](template-customization.md#custom-file-header-path) +- [`--custom-formatters`](template-customization.md#custom-formatters) +- [`--custom-formatters-kwargs`](template-customization.md#custom-formatters-kwargs) +- [`--custom-template-dir`](template-customization.md#custom-template-dir) + +### D {#d} + +- [`--dataclass-arguments`](model-customization.md#dataclass-arguments) +- [`--debug`](utility-options.md#debug) +- [`--default-values`](field-customization.md#default-values) +- [`--disable-appending-item-suffix`](template-customization.md#disable-appending-item-suffix) +- [`--disable-future-imports`](typing-customization.md#disable-future-imports) +- [`--disable-timestamp`](template-customization.md#disable-timestamp) +- [`--disable-warnings`](general-options.md#disable-warnings) +- [`--duplicate-name-suffix`](model-customization.md#duplicate-name-suffix) + +### E {#e} + +- [`--empty-enum-field-name`](field-customization.md#empty-enum-field-name) +- [`--enable-command-header`](template-customization.md#enable-command-header) +- [`--enable-faux-immutability`](model-customization.md#enable-faux-immutability) +- [`--enable-version-header`](template-customization.md#enable-version-header) +- [`--encoding`](base-options.md#encoding) +- [`--enum-field-as-literal`](typing-customization.md#enum-field-as-literal) +- [`--enum-field-as-literal-map`](typing-customization.md#enum-field-as-literal-map) +- [`--extra-fields`](field-customization.md#extra-fields) +- [`--extra-template-data`](template-customization.md#extra-template-data) + +### F {#f} + +- [`--field-constraints`](field-customization.md#field-constraints) +- [`--field-extra-keys`](field-customization.md#field-extra-keys) +- [`--field-extra-keys-without-x-prefix`](field-customization.md#field-extra-keys-without-x-prefix) +- [`--field-include-all-keys`](field-customization.md#field-include-all-keys) +- [`--field-type-collision-strategy`](field-customization.md#field-type-collision-strategy) +- [`--force-optional`](model-customization.md#force-optional) +- [`--formatters`](template-customization.md#formatters) +- [`--frozen-dataclasses`](model-customization.md#frozen-dataclasses) + +### G {#g} + +- [`--generate-cli-command`](general-options.md#generate-cli-command) +- [`--generate-prompt`](utility-options.md#generate-prompt) +- [`--generate-pyproject-config`](general-options.md#generate-pyproject-config) +- [`--graphql-no-typename`](graphql-only-options.md#graphql-no-typename) + +### H {#h} + +- [`--help`](utility-options.md#help) +- [`--http-headers`](general-options.md#http-headers) +- [`--http-ignore-tls`](general-options.md#http-ignore-tls) +- [`--http-query-parameters`](general-options.md#http-query-parameters) +- [`--http-timeout`](general-options.md#http-timeout) + +### I {#i} + +- [`--ignore-enum-constraints`](typing-customization.md#ignore-enum-constraints) +- [`--ignore-pyproject`](general-options.md#ignore-pyproject) +- [`--include-path-parameters`](openapi-only-options.md#include-path-parameters) +- [`--input`](base-options.md#input) +- [`--input-file-type`](base-options.md#input-file-type) +- [`--input-model`](base-options.md#input-model) +- [`--input-model-ref-strategy`](base-options.md#input-model-ref-strategy) + +### K {#k} + +- [`--keep-model-order`](model-customization.md#keep-model-order) +- [`--keyword-only`](model-customization.md#keyword-only) + +### M {#m} + +- [`--model-extra-keys`](model-customization.md#model-extra-keys) +- [`--model-extra-keys-without-x-prefix`](model-customization.md#model-extra-keys-without-x-prefix) +- [`--module-split-mode`](general-options.md#module-split-mode) + +### N {#n} + +- [`--naming-strategy`](model-customization.md#naming-strategy) +- [`--no-alias`](field-customization.md#no-alias) +- [`--no-color`](utility-options.md#no-color) +- [`--no-treat-dot-as-module`](template-customization.md#no-treat-dot-as-module) +- [`--no-use-specialized-enum`](typing-customization.md#no-use-specialized-enum) +- [`--no-use-standard-collections`](typing-customization.md#no-use-standard-collections) +- [`--no-use-union-operator`](typing-customization.md#no-use-union-operator) + +### O {#o} + +- [`--openapi-include-paths`](openapi-only-options.md#openapi-include-paths) +- [`--openapi-scopes`](openapi-only-options.md#openapi-scopes) +- [`--original-field-name-delimiter`](field-customization.md#original-field-name-delimiter) +- [`--output`](base-options.md#output) +- [`--output-date-class`](typing-customization.md#output-date-class) +- [`--output-datetime-class`](typing-customization.md#output-datetime-class) +- [`--output-model-type`](model-customization.md#output-model-type) + +### P {#p} + +- [`--parent-scoped-naming`](model-customization.md#parent-scoped-naming) +- [`--profile`](utility-options.md#profile) + +### R {#r} + +- [`--read-only-write-only-model-type`](openapi-only-options.md#read-only-write-only-model-type) +- [`--remove-special-field-name-prefix`](field-customization.md#remove-special-field-name-prefix) +- [`--reuse-model`](model-customization.md#reuse-model) +- [`--reuse-scope`](model-customization.md#reuse-scope) + +### S {#s} + +- [`--set-default-enum-member`](field-customization.md#set-default-enum-member) +- [`--shared-module-name`](general-options.md#shared-module-name) +- [`--skip-root-model`](model-customization.md#skip-root-model) +- [`--snake-case-field`](field-customization.md#snake-case-field) +- [`--special-field-name-prefix`](field-customization.md#special-field-name-prefix) +- [`--strict-nullable`](model-customization.md#strict-nullable) +- [`--strict-types`](typing-customization.md#strict-types) +- [`--strip-default-none`](model-customization.md#strip-default-none) + +### T {#t} + +- [`--target-pydantic-version`](model-customization.md#target-pydantic-version) +- [`--target-python-version`](model-customization.md#target-python-version) +- [`--treat-dot-as-module`](template-customization.md#treat-dot-as-module) +- [`--type-mappings`](typing-customization.md#type-mappings) +- [`--type-overrides`](typing-customization.md#type-overrides) + +### U {#u} + +- [`--union-mode`](model-customization.md#union-mode) +- [`--url`](base-options.md#url) +- [`--use-annotated`](typing-customization.md#use-annotated) +- [`--use-attribute-docstrings`](field-customization.md#use-attribute-docstrings) +- [`--use-decimal-for-multiple-of`](typing-customization.md#use-decimal-for-multiple-of) +- [`--use-default`](model-customization.md#use-default) +- [`--use-default-factory-for-optional-nested-models`](model-customization.md#use-default-factory-for-optional-nested-models) +- [`--use-default-kwarg`](model-customization.md#use-default-kwarg) +- [`--use-double-quotes`](template-customization.md#use-double-quotes) +- [`--use-enum-values-in-discriminator`](field-customization.md#use-enum-values-in-discriminator) +- [`--use-exact-imports`](template-customization.md#use-exact-imports) +- [`--use-field-description`](field-customization.md#use-field-description) +- [`--use-field-description-example`](field-customization.md#use-field-description-example) +- [`--use-frozen-field`](model-customization.md#use-frozen-field) +- [`--use-generic-base-class`](model-customization.md#use-generic-base-class) +- [`--use-generic-container-types`](typing-customization.md#use-generic-container-types) +- [`--use-inline-field-description`](field-customization.md#use-inline-field-description) +- [`--use-non-positive-negative-number-constrained-types`](typing-customization.md#use-non-positive-negative-number-constrained-types) +- [`--use-one-literal-as-default`](model-customization.md#use-one-literal-as-default) +- [`--use-operation-id-as-name`](openapi-only-options.md#use-operation-id-as-name) +- [`--use-pendulum`](typing-customization.md#use-pendulum) +- [`--use-root-model-type-alias`](typing-customization.md#use-root-model-type-alias) +- [`--use-schema-description`](field-customization.md#use-schema-description) +- [`--use-serialization-alias`](field-customization.md#use-serialization-alias) +- [`--use-serialize-as-any`](model-customization.md#use-serialize-as-any) +- [`--use-specialized-enum`](typing-customization.md#use-specialized-enum) +- [`--use-standard-collections`](typing-customization.md#use-standard-collections) +- [`--use-standard-primitive-types`](typing-customization.md#use-standard-primitive-types) +- [`--use-status-code-in-response-name`](openapi-only-options.md#use-status-code-in-response-name) +- [`--use-subclass-enum`](model-customization.md#use-subclass-enum) +- [`--use-title-as-name`](field-customization.md#use-title-as-name) +- [`--use-tuple-for-fixed-items`](typing-customization.md#use-tuple-for-fixed-items) +- [`--use-type-alias`](typing-customization.md#use-type-alias) +- [`--use-union-operator`](typing-customization.md#use-union-operator) +- [`--use-unique-items-as-set`](typing-customization.md#use-unique-items-as-set) + +### V {#v} + +- [`--validation`](openapi-only-options.md#validation) +- [`--validators`](template-customization.md#validators) +- [`--version`](utility-options.md#version) + +### W {#w} + +- [`--watch`](general-options.md#watch) +- [`--watch-delay`](general-options.md#watch-delay) +- [`--wrap-string-literal`](template-customization.md#wrap-string-literal) + +--- + +# Base Options + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/base-options/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--encoding`](#encoding) | Specify character encoding for input and output files. | +| [`--input`](#input) | Specify the input schema file path. | +| [`--input-file-type`](#input-file-type) | Specify the input file type for code generation. | +| [`--input-model`](#input-model) | Import a Python type or dict schema from a module. | +| [`--input-model-ref-strategy`](#input-model-ref-strategy) | Strategy for referenced types when using --input-model. | +| [`--output`](#output) | Specify the destination path for generated Python code. | +| [`--url`](#url) | Fetch schema from URL with custom HTTP headers. | + +--- + +## `--encoding` {#encoding} + +Specify character encoding for input and output files. + +The `--encoding` flag sets the character encoding used when reading +the schema file and writing the generated Python code. This is useful +for schemas containing non-ASCII characters (e.g., Japanese, Chinese). +Default is UTF-8, which is the standard encoding for JSON and most modern text files. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --encoding utf-8 # (1)! + ``` + + 1. :material-arrow-left: `--encoding` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ๆ—ฅๆœฌ่ชžModel", + "description": "ใƒขใƒ‡ใƒซใฎ่ชฌๆ˜Žๆ–‡", + "type": "object", + "properties": { + "ๅๅ‰": { + "type": "string", + "description": "ใƒฆใƒผใ‚ถใƒผๅ" + }, + "ๅนด้ฝข": { + "type": "integer" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: encoding_test.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class ๆ—ฅๆœฌ่ชžModel(BaseModel): + ๅๅ‰: str | None = Field(None, description='ใƒฆใƒผใ‚ถใƒผๅ') + ๅนด้ฝข: int | None = None + ``` + +--- + +## `--input` {#input} + +Specify the input schema file path. + +The `--input` flag specifies the path to the schema file (JSON Schema, +OpenAPI, GraphQL, etc.). Multiple input files can be specified to merge +schemas. Required unless using `--url` to fetch schema from a URL. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --input pet_simple.json --output output.py # (1)! + ``` + + 1. :material-arrow-left: `--input` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet_simple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--input-file-type` {#input-file-type} + +Specify the input file type for code generation. + +The `--input-file-type` flag explicitly sets the input format. + +**Important distinction:** + +- Use `jsonschema`, `openapi`, or `graphql` for **schema definition files** +- Use `json`, `yaml`, or `csv` for **raw sample data** to automatically infer a schema + +For example, if you have a JSON Schema written in YAML format, use `--input-file-type jsonschema`, +not `--input-file-type yaml`. The `yaml` type treats the file as raw data and infers a schema from it. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --input-file-type json # (1)! + ``` + + 1. :material-arrow-left: `--input-file-type` - the option documented here + +??? example "Examples" + + === "JSON" + + **Input Schema:** + + ```json + { + "Pet": { + "name": "dog", + "age": 2 + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + name: str + age: int + + + class Model(BaseModel): + Pet: Pet + ``` + + === "YAML" + + **Input Schema:** + + ```yaml + Pet: + name: cat + age: 3 + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + name: str + age: int + + + class Model(BaseModel): + Pet: Pet + ``` + +--- + +## `--input-model` {#input-model} + +Import a Python type or dict schema from a module. + +Use the format `module:Object` or `path/to/file.py:Object` to specify the type. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --input-model mymodule:MyModel # (1)! + ``` + + 1. :material-arrow-left: `--input-model` - the option documented here + +??? example "Examples" + + **Output:** + +--- + +## `--input-model-ref-strategy` {#input-model-ref-strategy} + +Strategy for referenced types when using --input-model. + +The `--input-model-ref-strategy` option determines whether to regenerate or import +referenced types. Use `regenerate-all` (default) to regenerate all types, +`reuse-foreign` to import types from different families (like enums when generating +dataclasses) while regenerating same-family types, or `reuse-all` to import all +referenced types directly. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --input-model-ref-strategy reuse-foreign # (1)! + ``` + + 1. :material-arrow-left: `--input-model-ref-strategy` - the option documented here + +??? example "Examples" + + **Output:** + +--- + +## `--output` {#output} + +Specify the destination path for generated Python code. + +The `--output` flag specifies where to write the generated Python code. +It can be either a file path (single-file output) or a directory path +(multi-file output for modular schemas). If omitted, the generated code +is written to stdout. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --input pet_simple.json --output output.py # (1)! + ``` + + 1. :material-arrow-left: `--output` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet_simple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--url` {#url} + +Fetch schema from URL with custom HTTP headers. + +The `--url` flag specifies a remote URL to fetch the schema from instead of +a local file. The `--http-headers` flag adds custom HTTP headers to the request, +useful for authentication (e.g., Bearer tokens) or custom API requirements. +Format: `HeaderName:HeaderValue`. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --url https://api.example.com/schema.json --http-headers "Authorization:Bearer token" # (1)! + ``` + + 1. :material-arrow-left: `--url` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: https://api.example.com/schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +--- + +# Model Customization + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/model-customization/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--allow-extra-fields`](#allow-extra-fields) | Allow extra fields in generated Pydantic models (extra='allo... | +| [`--allow-population-by-field-name`](#allow-population-by-field-name) | Allow Pydantic model population by field name (not just alia... | +| [`--base-class`](#base-class) | Specify a custom base class for generated models. | +| [`--base-class-map`](#base-class-map) | Specify different base classes for specific models via JSON ... | +| [`--class-name`](#class-name) | Override the auto-generated class name with a custom name. | +| [`--class-name-affix-scope`](#class-name-affix-scope) | Control which classes receive the prefix/suffix. | +| [`--class-name-prefix`](#class-name-prefix) | Add a prefix to all generated class names. | +| [`--class-name-suffix`](#class-name-suffix) | Add a suffix to all generated class names. | +| [`--collapse-reuse-models`](#collapse-reuse-models) | Collapse duplicate models by replacing references instead of... | +| [`--collapse-root-models`](#collapse-root-models) | Inline root model definitions instead of creating separate w... | +| [`--collapse-root-models-name-strategy`](#collapse-root-models-name-strategy) | Select which name to keep when collapsing root models with o... | +| [`--dataclass-arguments`](#dataclass-arguments) | Customize dataclass decorator arguments via JSON dictionary.... | +| [`--duplicate-name-suffix`](#duplicate-name-suffix) | Customize suffix for duplicate model names. | +| [`--enable-faux-immutability`](#enable-faux-immutability) | Enable faux immutability in Pydantic v1 models (allow_mutati... | +| [`--force-optional`](#force-optional) | Force all fields to be Optional regardless of required statu... | +| [`--frozen-dataclasses`](#frozen-dataclasses) | Generate frozen dataclasses with optional keyword-only field... | +| [`--keep-model-order`](#keep-model-order) | Keep model definition order as specified in schema. | +| [`--keyword-only`](#keyword-only) | Generate dataclasses with keyword-only fields (Python 3.10+)... | +| [`--model-extra-keys`](#model-extra-keys) | Add model-level schema extensions to ConfigDict json_schema_... | +| [`--model-extra-keys-without-x-prefix`](#model-extra-keys-without-x-prefix) | Strip x- prefix from model-level schema extensions and add t... | +| [`--naming-strategy`](#naming-strategy) | Use parent-prefixed naming strategy for duplicate model name... | +| [`--output-model-type`](#output-model-type) | Select the output model type (Pydantic v1/v2, dataclasses, T... | +| [`--parent-scoped-naming`](#parent-scoped-naming) | Namespace models by their parent scope to avoid naming confl... | +| [`--reuse-model`](#reuse-model) | Reuse identical model definitions instead of generating dupl... | +| [`--reuse-scope`](#reuse-scope) | Scope for model reuse detection (root or tree). | +| [`--skip-root-model`](#skip-root-model) | Skip generation of root model when schema contains nested de... | +| [`--strict-nullable`](#strict-nullable) | Treat default field as a non-nullable field. | +| [`--strip-default-none`](#strip-default-none) | Remove fields with None as default value from generated mode... | +| [`--target-pydantic-version`](#target-pydantic-version) | Target Pydantic version for generated code compatibility. | +| [`--target-python-version`](#target-python-version) | Target Python version for generated code syntax and imports.... | +| [`--union-mode`](#union-mode) | Union mode for combining anyOf/oneOf schemas (smart or left_... | +| [`--use-default`](#use-default) | Use default values from schema in generated models. | +| [`--use-default-factory-for-optional-nested-models`](#use-default-factory-for-optional-nested-models) | Generate default_factory for optional nested model fields. | +| [`--use-default-kwarg`](#use-default-kwarg) | Use default= keyword argument instead of positional argument... | +| [`--use-frozen-field`](#use-frozen-field) | Generate frozen (immutable) field definitions for readOnly p... | +| [`--use-generic-base-class`](#use-generic-base-class) | Generate a shared base class with model configuration to avo... | +| [`--use-one-literal-as-default`](#use-one-literal-as-default) | Use single literal value as default when enum has only one o... | +| [`--use-serialize-as-any`](#use-serialize-as-any) | Wrap fields with subtypes in Pydantic's SerializeAsAny. | +| [`--use-subclass-enum`](#use-subclass-enum) | Generate typed Enum subclasses for enums with specific field... | + +--- + +## `--allow-extra-fields` {#allow-extra-fields} + +Allow extra fields in generated Pydantic models (extra='allow'). + +The `--allow-extra-fields` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --allow-extra-fields # (1)! + ``` + + 1. :material-arrow-left: `--allow-extra-fields` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Extra, Field + + + class Pet(BaseModel): + class Config: + extra = Extra.allow + + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + class Config: + extra = Extra.allow + + __root__: list[Pet] + + + class User(BaseModel): + class Config: + extra = Extra.allow + + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + class Config: + extra = Extra.allow + + __root__: list[User] + + + class Id(BaseModel): + class Config: + extra = Extra.allow + + __root__: str + + + class Rules(BaseModel): + class Config: + extra = Extra.allow + + __root__: list[str] + + + class Error(BaseModel): + class Config: + extra = Extra.allow + + code: int + message: str + + + class Api(BaseModel): + class Config: + extra = 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(BaseModel): + class Config: + extra = Extra.allow + + __root__: list[Api] + + + class Event(BaseModel): + class Config: + extra = Extra.allow + + name: str | None = None + + + class Result(BaseModel): + class Config: + extra = Extra.allow + + event: Event | None = None + ``` + + === "Pydantic v2" + + ```python + # 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-population-by-field-name` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --allow-population-by-field-name # (1)! + ``` + + 1. :material-arrow-left: `--allow-population-by-field-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + === "Pydantic v1" + + ```python + # 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 + + + class Pet(BaseModel): + class Config: + allow_population_by_field_name = True + + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + class Config: + allow_population_by_field_name = True + + __root__: list[Pet] + + + class User(BaseModel): + class Config: + allow_population_by_field_name = True + + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + class Config: + allow_population_by_field_name = True + + __root__: list[User] + + + class Id(BaseModel): + class Config: + allow_population_by_field_name = True + + __root__: str + + + class Rules(BaseModel): + class Config: + allow_population_by_field_name = True + + __root__: list[str] + + + class Error(BaseModel): + class Config: + allow_population_by_field_name = True + + code: int + message: str + + + class Api(BaseModel): + class Config: + allow_population_by_field_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(BaseModel): + class Config: + allow_population_by_field_name = True + + __root__: list[Api] + + + class Event(BaseModel): + class Config: + allow_population_by_field_name = True + + name: str | None = None + + + class Result(BaseModel): + class Config: + allow_population_by_field_name = True + + event: Event | None = None + ``` + + === "Pydantic v2" + + ```python + # 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 + ``` + +--- + +## `--base-class` {#base-class} + +Specify a custom base class for generated models. + +The `--base-class` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --base-class custom_module.Base # (1)! + ``` + + 1. :material-arrow-left: `--base-class` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, Field + + from custom_module import Base + + + class Pet(Base): + id: int + name: str + tag: str | None = None + + + class Pets(Base): + __root__: list[Pet] + + + class User(Base): + id: int + name: str + tag: str | None = None + + + class Users(Base): + __root__: list[User] + + + class Id(Base): + __root__: str + + + class Rules(Base): + __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(Base): + __root__: list[Api] + + + class Event(Base): + name: str | None = None + + + class Result(Base): + event: Event | None = None + ``` + +--- + +## `--base-class-map` {#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. Priority: base-class-map > customBasePath > base-class. + +**Related:** [`--base-class`](model-customization.md#base-class) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --base-class-map "{"Person": "custom.bases.PersonBase", "Animal": "custom.bases.AnimalBase"}" # (1)! + ``` + + 1. :material-arrow-left: `--base-class-map` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + > **Error:** File not found: base_class_map.py + +--- + +## `--class-name` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --class-name ValidModelName # (1)! + ``` + + 1. :material-arrow-left: `--class-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # 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 = None + ``` + +--- + +## `--class-name-affix-scope` {#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`](model-customization.md#class-name-prefix), [`--class-name-suffix`](model-customization.md#class-name-suffix) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --class-name-suffix Schema --class-name-affix-scope models # (1)! + ``` + + 1. :material-arrow-left: `--class-name-affix-scope` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "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:** + + ```python + # 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` {#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`](model-customization.md#class-name-affix-scope), [`--class-name-suffix`](model-customization.md#class-name-suffix) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --class-name-prefix Api # (1)! + ``` + + 1. :material-arrow-left: `--class-name-prefix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "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:** + + ```python + # 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` {#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`](model-customization.md#class-name-affix-scope), [`--class-name-prefix`](model-customization.md#class-name-prefix) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --class-name-suffix Schema # (1)! + ``` + + 1. :material-arrow-left: `--class-name-suffix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "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:** + + ```python + # 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-reuse-models` {#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`](model-customization.md#reuse-model) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --reuse-model --collapse-reuse-models # (1)! + ``` + + 1. :material-arrow-left: `--collapse-reuse-models` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "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:** + + ```python + # 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: Head + ``` + +--- + +## `--collapse-root-models` {#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 v1/v2, dataclass, TypedDict, msgspec) handle const fields. + +**See also:** [Model Reuse and Deduplication](../model-reuse.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --collapse-root-models # (1)! + ``` + + 1. :material-arrow-left: `--collapse-root-models` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + 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:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: const.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal + + from pydantic import BaseModel, Field + + + class Api(BaseModel): + version: Literal['v1'] = Field( + 'v1', const=True, description='The version of this API' + ) + ``` + + === "Pydantic v2" + + ```python + # generated by datamodel-codegen: + # filename: const.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal + + from pydantic import BaseModel, Field + + + class Api(BaseModel): + version: Literal['v1'] = Field(..., description='The version of this API') + ``` + + === "dataclass" + + ```python + # generated by datamodel-codegen: + # filename: const.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from dataclasses import dataclass + from typing import Literal + + + @dataclass + class Api: + version: Literal['v1'] + ``` + + === "TypedDict" + + ```python + # generated by datamodel-codegen: + # filename: const.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal, TypedDict + + + class Api(TypedDict): + version: Literal['v1'] + ``` + + === "msgspec" + + ```python + # generated by datamodel-codegen: + # filename: const.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated, Literal + + from msgspec import Meta, Struct + + + class Api(Struct): + version: Annotated[Literal['v1'], Meta(description='The version of this API')] + ``` + + === "Without Option (Baseline)" + + ```python + # generated by datamodel-codegen: + # filename: const.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class ApiVersion(BaseModel): + __root__: str = Field('v1', const=True, description='The version of this API') + + + class Api(BaseModel): + version: ApiVersion + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "field": { + "anyOf": [ + {"$ref": "#/$defs/NullType1"}, + {"$ref": "#/$defs/NullType2"} + ] + } + }, + "$defs": { + "NullType1": { + "type": "null" + }, + "NullType2": { + "type": "null" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: collapse_root_models_empty_union.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class Model(BaseModel): + field: Any = None + ``` + +--- + +## `--collapse-root-models-name-strategy` {#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`](model-customization.md#collapse-root-models) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --collapse-root-models --collapse-root-models-name-strategy child # (1)! + ``` + + 1. :material-arrow-left: `--collapse-root-models-name-strategy` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # generated by datamodel-codegen: + # filename: collapse_root_models_name_strategy_child.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class FieldType2(BaseModel): + asText: str + + + class Model(BaseModel): + metadata: FieldType2 | None = None + ``` + +--- + +## `--dataclass-arguments` {#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`](model-customization.md#frozen-dataclasses), [`--keyword-only`](model-customization.md#keyword-only) + +**See also:** [Output Model Types](../what_is_the_difference_between_v1_and_v2.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass --dataclass-arguments "{"slots": true, "order": true}" # (1)! + ``` + + 1. :material-arrow-left: `--dataclass-arguments` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + 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:** + + ```python + # 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` {#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`](model-customization.md#naming-strategy) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --duplicate-name-suffix "{"model": "Schema"}" # (1)! + ``` + + 1. :material-arrow-left: `--duplicate-name-suffix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # 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} + +Enable faux immutability in Pydantic v1 models (allow_mutation=False). + +The `--enable-faux-immutability` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --enable-faux-immutability # (1)! + ``` + + 1. :material-arrow-left: `--enable-faux-immutability` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + === "Pydantic v1" + + ```python + # 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 + + + class Pet(BaseModel): + class Config: + allow_mutation = False + + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + class Config: + allow_mutation = False + + __root__: list[Pet] + + + class User(BaseModel): + class Config: + allow_mutation = False + + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + class Config: + allow_mutation = False + + __root__: list[User] + + + class Id(BaseModel): + class Config: + allow_mutation = False + + __root__: str + + + class Rules(BaseModel): + class Config: + allow_mutation = False + + __root__: list[str] + + + class Error(BaseModel): + class Config: + allow_mutation = False + + code: int + message: str + + + class Api(BaseModel): + class Config: + allow_mutation = False + + 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(BaseModel): + class Config: + allow_mutation = False + + __root__: list[Api] + + + class Event(BaseModel): + class Config: + allow_mutation = False + + name: str | None = None + + + class Result(BaseModel): + class Config: + allow_mutation = False + + event: Event | None = None + ``` + + === "Pydantic v2" + + ```python + # 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-optional} + +Force all fields to be Optional regardless of required status. + +The `--force-optional` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --force-optional # (1)! + ``` + + 1. :material-arrow-left: `--force-optional` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + + + class Pet(BaseModel): + id: int | None = 1 + name: str | None = None + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] | None = None + + + class User(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] | None = None + + + class Id(BaseModel): + __root__: str | None = None + + + class Rules(BaseModel): + __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(BaseModel): + __root__: list[Api] | None = None + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--frozen-dataclasses` {#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`](model-customization.md#keyword-only), [`--output-model-type`](model-customization.md#output-model-type) + +**See also:** [Output Model Types](../what_is_the_difference_between_v1_and_v2.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass --frozen-dataclasses # (1)! + ``` + + 1. :material-arrow-left: `--frozen-dataclasses` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # generated by datamodel-codegen: + # filename: simple_frozen_test.json + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from dataclasses import dataclass + + + @dataclass(frozen=True) + class User: + name: str + age: int + email: str | None = None + ``` + +--- + +## `--keep-model-order` {#keep-model-order} + +Keep model definition order as specified in schema. + +The `--keep-model-order` flag preserves the original definition order from the schema +instead of reordering models based on dependencies. This is useful when the order +of model definitions matters for documentation or readability. + +**Related:** [`--collapse-root-models`](model-customization.md#collapse-root-models) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --keep-model-order # (1)! + ``` + + 1. :material-arrow-left: `--keep-model-order` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "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:** + + ```python + # 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.update_forward_refs() + Dog.update_forward_refs() + PersonRelationships.update_forward_refs() + Person.update_forward_refs() + PersonsBestFriend.update_forward_refs() + ``` + +--- + +## `--keyword-only` {#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`](model-customization.md#frozen-dataclasses), [`--output-model-type`](model-customization.md#output-model-type), [`--target-python-version`](model-customization.md#target-python-version) + +**See also:** [Output Model Types](../what_is_the_difference_between_v1_and_v2.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass --frozen-dataclasses --keyword-only --target-python-version 3.10 # (1)! + ``` + + 1. :material-arrow-left: `--keyword-only` - the option documented here + +??? example "Examples" + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + ```python + # 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 + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + 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:** + + ```python + # 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' + ``` + +--- + +## `--model-extra-keys` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --model-extra-keys x-custom-metadata # (1)! + ``` + + 1. :material-arrow-left: `--model-extra-keys` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + === "Pydantic v2" + + ```python + # 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` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --model-extra-keys-without-x-prefix x-custom-metadata x-version # (1)! + ``` + + 1. :material-arrow-left: `--model-extra-keys-without-x-prefix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + === "Pydantic v2" + + ```python + # 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 + ``` + +--- + +## `--naming-strategy` {#naming-strategy} + +Use parent-prefixed naming strategy for duplicate model names. + +The `--naming-strategy parent-prefixed` flag prefixes model names with their +parent model name when duplicates occur. For example, if both `Order` and +`Cart` have an inline `Item` definition, they become `OrderItem` and `CartItem`. + +**Related:** [`--duplicate-name-suffix`](model-customization.md#duplicate-name-suffix), [`--parent-scoped-naming`](model-customization.md#parent-scoped-naming) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --naming-strategy parent-prefixed # (1)! + ``` + + 1. :material-arrow-left: `--naming-strategy` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # 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 + ``` + +--- + +## `--output-model-type` {#output-model-type} + +Select the output model type (Pydantic v1/v2, dataclasses, TypedDict, msgspec). + +The `--output-model-type` flag specifies which Python data model framework to use +for the generated code. Supported values include `pydantic.BaseModel`, +`pydantic_v2.BaseModel`, `dataclasses.dataclass`, `typing.TypedDict`, and +`msgspec.Struct`. + +**See also:** [Output Model Types](../what_is_the_difference_between_v1_and_v2.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic.BaseModel # (1)! + ``` + + 1. :material-arrow-left: `--output-model-type` - the option documented here + +??? example "Examples" + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$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:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: null_and_array.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class MyObjItem(BaseModel): + items: list[Any] | None + + + class Model(BaseModel): + my_obj: list[MyObjItem] + ``` + + === "Pydantic v2" + + ```python + # generated by datamodel-codegen: + # filename: null_and_array.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class MyObjItem(BaseModel): + items: list[Any] | None + + + class Model(BaseModel): + my_obj: list[MyObjItem] + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + 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:** + + === "Pydantic v1" + + ```python + # 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, TypeAlias + + from pydantic import BaseModel, Field + + 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. + """ + + + 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.update_forward_refs() + Person.update_forward_refs() + ``` + + === "dataclass" + + ```python + # 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` {#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:** Use --naming-strategy parent-prefixed instead. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --parent-scoped-naming --use-operation-id-as-name --openapi-scopes paths schemas parameters # (1)! + ``` + + 1. :material-arrow-left: `--parent-scoped-naming` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + ``` + +--- + +## `--reuse-model` {#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`](model-customization.md#collapse-root-models) + +**See also:** [Model Reuse and Deduplication](../model-reuse.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --reuse-model # (1)! + ``` + + 1. :material-arrow-left: `--reuse-model` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # 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 + + + 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(BaseModel): + __root__: list[RedistributeEnum] = Field( + ..., description='Redistribute type for routes.' + ) + ``` + +--- + +## `--reuse-scope` {#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](../model-reuse.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --reuse-model --reuse-scope tree # (1)! + ``` + + 1. :material-arrow-left: `--reuse-scope` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + # 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:** + + ```python + # __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 + ``` + +--- + +## `--skip-root-model` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --skip-root-model # (1)! + ``` + + 1. :material-arrow-left: `--skip-root-model` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # generated by datamodel-codegen: + # filename: skip_root_model_test.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Person(BaseModel): + name: str + age: int | None = None + ``` + +--- + +## `--strict-nullable` {#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`](model-customization.md#use-default) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --strict-nullable # (1)! + ``` + + 1. :material-arrow-left: `--strict-nullable` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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 + required: + - comments + - oneOfComments + ``` + + **Output:** + + ```python + # 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 + + + 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(BaseModel): + __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(BaseModel): + __root__: list[EmailItem] + + + class Id(BaseModel): + __root__: int + + + class Description(BaseModel): + __root__: str | None = 'example' + + + class Name(BaseModel): + __root__: str | None = None + + + class Tag(BaseModel): + __root__: str + + + class Notes(BaseModel): + comments: list[str] = Field(default_factory=list) + + + class Options(BaseModel): + comments: list[str | None] + oneOfComments: list[str | float | None] + ``` + +--- + +## `--strip-default-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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --strip-default-none # (1)! + ``` + + 1. :material-arrow-left: `--strip-default-none` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + + + class Pet(BaseModel): + id: int + name: str + tag: str | None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None + + + class Result(BaseModel): + event: Event | None + ``` + +--- + +## `--target-pydantic-version` {#target-pydantic-version} + +Target Pydantic version for generated code compatibility. + +The `--target-pydantic-version` flag controls Pydantic version-specific config: + +- **2**: Uses `populate_by_name=True` (compatible with Pydantic 2.0-2.10) +- **2.11**: Uses `validate_by_name=True` (for Pydantic 2.11+) + +This prevents breaking changes when generated code is used on older Pydantic versions. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --target-pydantic-version 2.11 --allow-population-by-field-name --output-model-type pydantic_v2.BaseModel # (1)! + ``` + + 1. :material-arrow-left: `--target-pydantic-version` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + ```python + # 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 = None + ``` + +--- + +## `--target-python-version` {#target-python-version} + +Target Python version for generated code syntax and imports. + +The `--target-python-version` flag controls Python version-specific syntax: + +- **Python 3.10-3.11**: Uses `X | None` union operator, `TypeAlias` annotation +- **Python 3.12+**: Uses `type` statement for type aliases + +This affects import statements and type annotation syntax in generated code. + +**See also:** [CI/CD Integration](../ci-cd.md), [Python Version Compatibility](../python-version-compatibility.md), [Output Model Types](../what_is_the_difference_between_v1_and_v2.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --target-python-version 3.10 --use-standard-collections # (1)! + ``` + + 1. :material-arrow-left: `--target-python-version` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + === "Python 3.10" + + ```python + # 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 = None + ``` + +--- + +## `--union-mode` {#union-mode} + +Union mode for combining anyOf/oneOf schemas (smart or left_to_right). + +The `--union-mode` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --union-mode left_to_right --output-model-type pydantic_v2.BaseModel # (1)! + ``` + + 1. :material-arrow-left: `--union-mode` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # 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} + +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. + +**Related:** [`--strict-nullable`](model-customization.md#strict-nullable) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --use-default # (1)! + ``` + + 1. :material-arrow-left: `--use-default` - the option documented here + +!!! warning "Fields with defaults become nullable" + When using `--use-default`, fields with default values are generated as nullable + types (e.g., `str | None` instead of `str`), even if the schema does not allow + null values. + + If you want fields to strictly follow the schema's type definition (non-nullable), + use `--strict-nullable` together with `--use-default`. + + +!!! note "Future behavior change" + In a future major version, the default behavior of `--use-default` may change to + generate non-nullable types that match the schema definition (equivalent to using + `--strict-nullable`). If you rely on the current nullable behavior, consider + explicitly handling this in your code. + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "Use default with const", + "properties": { + "foo": { + "const": "foo" + } + } + } + ``` + + **Output:** + + ```python + # 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'] = 'foo' + ``` + +--- + +## `--use-default-factory-for-optional-nested-models` {#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)` + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-default-factory-for-optional-nested-models # (1)! + ``` + + 1. :material-arrow-left: `--use-default-factory-for-optional-nested-models` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + === "Pydantic v2" + + ```python + # 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) + ``` + + === "dataclass" + + ```python + # 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) + ``` + + === "msgspec" + + ```python + # 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-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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-default-kwarg # (1)! + ``` + + 1. :material-arrow-left: `--use-default-kwarg` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + type A { + field: String! + optionalField: String + listField: [String!]! + listOptionalField: [String]! + optionalListField: [String!] + optionalListOptionalField: [String] + listListField:[[String!]!]! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: annotated.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal, TypeAlias + + from pydantic import BaseModel, Field + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + 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-frozen-field` {#use-frozen-field} + +Generate frozen (immutable) field definitions for readOnly properties. + +The `--use-frozen-field` flag generates frozen field definitions: +- Pydantic v1: `Field(allow_mutation=False)` +- Pydantic v2: `Field(frozen=True)` +- Dataclasses: silently ignored (no frozen fields generated) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-frozen-field # (1)! + ``` + + 1. :material-arrow-left: `--use-frozen-field` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: use_frozen_field.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from datetime import datetime + + from pydantic import BaseModel, Field + + + class User(BaseModel): + class Config: + validate_assignment = True + + id: int = Field(..., allow_mutation=False, description='Server-generated ID') + name: str + password: str = Field(..., description='User password') + created_at: datetime | None = Field(None, allow_mutation=False) + ``` + + === "Pydantic v2" + + ```python + # 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) + ``` + + === "dataclass" + + ```python + # generated by datamodel-codegen: + # filename: use_frozen_field.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from dataclasses import dataclass + + + @dataclass + class User: + id: int + name: str + password: str + created_at: str | None = None + ``` + +--- + +## `--use-generic-base-class` {#use-generic-base-class} + +Generate a shared base class with model configuration to avoid repetition (DRY). + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --extra-fields forbid --output-model-type pydantic_v2.BaseModel --use-generic-base-class # (1)! + ``` + + 1. :material-arrow-left: `--use-generic-base-class` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "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:** + + ```python + # 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-one-literal-as-default` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-one-literal-as-default --enum-field-as-literal one # (1)! + ``` + + 1. :material-arrow-left: `--use-one-literal-as-default` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + + + 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(BaseModel): + __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(BaseModel): + __root__: Literal['pet'] = 'pet' + + + class ArrayEnum(BaseModel): + __root__: list[Literal['cat'] | Literal['dog']] + + + class NestedVersionEnum(Enum): + RC1 = 'RC1' + RC1N = 'RC1N' + RC2 = 'RC2' + RC2N = 'RC2N' + RC3 = 'RC3' + RC4 = 'RC4' + + + class NestedVersion(BaseModel): + __root__: NestedVersionEnum | None = Field( + 'RC1', description='nullable enum', example='RC2' + ) + + + class NestedNullableEnum(BaseModel): + nested_version: NestedVersion | None = Field( + default_factory=lambda: NestedVersion.parse_obj('RC1'), + description='nullable enum', + example='RC2', + ) + + + class VersionEnum(Enum): + RC1 = 'RC1' + RC1N = 'RC1N' + RC2 = 'RC2' + RC2N = 'RC2N' + RC3 = 'RC3' + RC4 = 'RC4' + + + class Version(BaseModel): + __root__: VersionEnum | None = Field( + 'RC1', description='nullable enum', example='RC2' + ) + ``` + +--- + +## `--use-serialize-as-any` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-serialize-as-any # (1)! + ``` + + 1. :material-arrow-left: `--use-serialize-as-any` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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-subclass-enum` {#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. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-subclass-enum # (1)! + ``` + + 1. :material-arrow-left: `--use-subclass-enum` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + "Employee shift status" + enum EmployeeShiftStatus { + "not on shift" + NOT_ON_SHIFT + "on shift" + ON_SHIFT + } + + enum Color { + RED + GREEN + BLUE + } + + enum EnumWithOneField { + FIELD + } + ``` + + **Output:** + + ```python + # 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 import TypeAlias + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + 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' + ``` + +--- + +--- + +# Field Customization + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/field-customization/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--aliases`](#aliases) | Apply custom field and class name aliases from JSON file. | +| [`--capitalize-enum-members`](#capitalize-enum-members) | Capitalize enum member names to UPPER_CASE format. | +| [`--default-values`](#default-values) | Override field default values from external JSON file. | +| [`--empty-enum-field-name`](#empty-enum-field-name) | Name for empty string enum field values. | +| [`--extra-fields`](#extra-fields) | Configure how generated models handle extra fields not defin... | +| [`--field-constraints`](#field-constraints) | Generate Field() with validation constraints from schema. | +| [`--field-extra-keys`](#field-extra-keys) | Include specific extra keys in Field() definitions. | +| [`--field-extra-keys-without-x-prefix`](#field-extra-keys-without-x-prefix) | Include schema extension keys in Field() without requiring '... | +| [`--field-include-all-keys`](#field-include-all-keys) | Include all schema keys in Field() json_schema_extra. | +| [`--field-type-collision-strategy`](#field-type-collision-strategy) | Rename type class instead of field when names collide (Pydan... | +| [`--no-alias`](#no-alias) | Disable Field alias generation for non-Python-safe property ... | +| [`--original-field-name-delimiter`](#original-field-name-delimiter) | Specify delimiter for original field names when using snake-... | +| [`--remove-special-field-name-prefix`](#remove-special-field-name-prefix) | Remove the special prefix from field names. | +| [`--set-default-enum-member`](#set-default-enum-member) | Set the first enum member as the default value for enum fiel... | +| [`--snake-case-field`](#snake-case-field) | Convert field names to snake_case format. | +| [`--special-field-name-prefix`](#special-field-name-prefix) | Prefix to add to special field names (like reserved keywords... | +| [`--use-attribute-docstrings`](#use-attribute-docstrings) | Generate field descriptions as attribute docstrings instead ... | +| [`--use-enum-values-in-discriminator`](#use-enum-values-in-discriminator) | Use enum values in discriminator mappings for union types. | +| [`--use-field-description`](#use-field-description) | Include schema descriptions as Field docstrings. | +| [`--use-field-description-example`](#use-field-description-example) | Add field examples to docstrings. | +| [`--use-inline-field-description`](#use-inline-field-description) | Add field descriptions as inline comments. | +| [`--use-schema-description`](#use-schema-description) | Use schema description as class docstring. | +| [`--use-serialization-alias`](#use-serialization-alias) | Use serialization_alias instead of alias for field aliasing ... | +| [`--use-title-as-name`](#use-title-as-name) | Use schema title as the generated class name. | + +--- + +## `--aliases` {#aliases} + +Apply custom field and class name aliases from JSON file. + +The `--aliases` option allows renaming fields and classes via a JSON mapping file, +providing fine-grained control over generated names independent of schema definitions. + +**See also:** [Field Aliases](../aliases.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --aliases openapi/aliases.json --target-python-version 3.10 # (1)! + ``` + + 1. :material-arrow-left: `--aliases` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + 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:** + + === "Pydantic v1" + + ```python + # 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 + + + class Pet(BaseModel): + id_: int = Field(..., alias='id') + name_: str = Field(..., alias='name') + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id_: int = Field(..., alias='id') + name_: str = Field(..., alias='name') + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name_: str | None = Field(None, alias='name') + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "msgspec" + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated, TypeAlias + + from msgspec import UNSET, Meta, Struct, UnsetType, field + + + class Pet(Struct): + id_: int = field(name='id') + name_: str = field(name='name') + tag: str | UnsetType = UNSET + + + Pets: TypeAlias = list[Pet] + + + class User(Struct): + id_: int = field(name='id') + name_: str = field(name='name') + tag: str | UnsetType = UNSET + + + Users: TypeAlias = list[User] + + + Id: TypeAlias = str + + + Rules: TypeAlias = list[str] + + + class Error(Struct): + code: int + message: str + + + class Api(Struct): + apiKey: ( + Annotated[str, Meta(description='To be used as a dataset parameter value')] + | UnsetType + ) = UNSET + apiVersionNumber: ( + Annotated[str, Meta(description='To be used as a version parameter value')] + | UnsetType + ) = UNSET + apiUrl: ( + Annotated[str, Meta(description="The URL describing the dataset's fields")] + | UnsetType + ) = UNSET + apiDocumentationUrl: ( + Annotated[str, Meta(description='A URL to the API console for each API')] + | UnsetType + ) = UNSET + + + Apis: TypeAlias = list[Api] + + + class Event(Struct): + name_: str | UnsetType = field(name='name', default=UNSET) + + + class Result(Struct): + event: Event | UnsetType = UNSET + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "Root", + "properties": { + "name": { + "type": "string" + }, + "user": { + "type": "object", + "title": "User", + "properties": { + "name": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, + "address": { + "type": "object", + "title": "Address", + "properties": { + "name": { + "type": "string" + }, + "city": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: hierarchical_aliases.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class User(BaseModel): + user_name: str | None = Field(None, alias='name') + id: int | None = None + + + class Address(BaseModel): + address_name: str | None = Field(None, alias='name') + city: str | None = None + + + class Root(BaseModel): + root_name: str | None = Field(None, alias='name') + user: User | None = Field(None, title='User') + address: Address | None = Field(None, title='Address') + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + scalar DateTime + + type DateTimePeriod { + from: DateTime! + to: DateTime! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: field-aliases.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal, TypeAlias + + from pydantic import BaseModel, Field + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + DateTime: TypeAlias = str + + + 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. + """ + + + class DateTimePeriod(BaseModel): + periodFrom: DateTime = Field(..., alias='from') + periodTo: DateTime = Field(..., alias='to') + typename__: Literal['DateTimePeriod'] | None = Field( + 'DateTimePeriod', alias='__typename' + ) + ``` + +--- + +## `--capitalize-enum-members` {#capitalize-enum-members} + +Capitalize enum member names to UPPER_CASE format. + +The `--capitalize-enum-members` flag converts enum member names to +UPPER_CASE format (e.g., `active` becomes `ACTIVE`), following Python +naming conventions for constants. + +**Aliases:** `--capitalise-enum-members` | **Related:** [`--snake-case-field`](field-customization.md#snake-case-field) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --capitalize-enum-members # (1)! + ``` + + 1. :material-arrow-left: `--capitalize-enum-members` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "string", + "enum": [ + "snake_case", + "CAP_CASE", + "CamelCase", + "UPPERCASE" + ] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: many_case_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + + class Model(Enum): + SNAKE_CASE = 'snake_case' + CAP_CASE = 'CAP_CASE' + CAMEL_CASE = 'CamelCase' + UPPERCASE = 'UPPERCASE' + ``` + +--- + +## `--default-values` {#default-values} + +Override field default values from external JSON file. + +The `--default-values` option allows specifying default values for fields via a JSON file. +Supports scoped format (ClassName.field) for hierarchical overrides. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --default-values default_values/scoped_defaults.json # (1)! + ``` + + 1. :material-arrow-left: `--default-values` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "User": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "page": { + "type": "integer" + } + }, + "required": ["name"] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: default_values_override.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class Model(BaseModel): + __root__: Any + + + class User(BaseModel): + name: str + status: str | None = 'active' + page: int | None = 1 + ``` + +--- + +## `--empty-enum-field-name` {#empty-enum-field-name} + +Name for empty string enum field values. + +The `--empty-enum-field-name` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --empty-enum-field-name empty # (1)! + ``` + + 1. :material-arrow-left: `--empty-enum-field-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "string", + "enum": [ + true, + false, + "", + "\n", + "\r\n", + "\t", + "\\x08", + null, + "\\" + ] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: special_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel + + + class ModelEnum(Enum): + True_ = True + False_ = False + empty = '' + field_ = '\n' + field__ = '\r\n' + field__1 = '\t' + field_x08 = '\\x08' + field__2 = '\\' + + + class Model(BaseModel): + __root__: ModelEnum | None = None + ``` + +--- + +## `--extra-fields` {#extra-fields} + +Configure how generated models handle extra fields not defined in schema. + +The `--extra-fields` flag sets the generated models to allow, forbid, or +ignore extra fields. With `--extra-fields allow`, models will accept and +store fields not defined in the schema. Options: allow, ignore, forbid. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --extra-fields allow # (1)! + ``` + + 1. :material-arrow-left: `--extra-fields` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + 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:** + + ```python + # 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, TypeAlias + + from pydantic import BaseModel, Extra, Field + + 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. + """ + + + class Film(BaseModel): + class Config: + extra = Extra.allow + + characters: list[Person] + characters_ids: list[ID] + director: String + episode_id: Int + id: ID + opening_crawl: String + planets: list[Planet] + planets_ids: list[ID] + producer: String | None = None + release_date: String + species: list[Species] + species_ids: list[ID] + starships: list[Starship] + starships_ids: list[ID] + title: String + vehicles: list[Vehicle] + vehicles_ids: list[ID] + typename__: Literal['Film'] | None = Field('Film', alias='__typename') + + + class Person(BaseModel): + class Config: + extra = Extra.allow + + birth_year: String | None = None + eye_color: String | None = None + films: list[Film] + films_ids: list[ID] + gender: String | None = None + hair_color: String | None = None + height: Int | None = None + homeworld: Planet | None = None + homeworld_id: ID | None = None + id: ID + mass: Int | None = None + name: String + skin_color: String | None = None + species: list[Species] + species_ids: list[ID] + starships: list[Starship] + starships_ids: list[ID] + vehicles: list[Vehicle] + vehicles_ids: list[ID] + typename__: Literal['Person'] | None = Field('Person', alias='__typename') + + + class Planet(BaseModel): + class Config: + extra = Extra.allow + + climate: String | None = None + diameter: String | None = None + films: list[Film] + films_ids: list[ID] + gravity: String | None = None + id: ID + name: String + orbital_period: String | None = None + population: String | None = None + residents: list[Person] + residents_ids: list[ID] + rotation_period: String | None = None + surface_water: String | None = None + terrain: String | None = None + typename__: Literal['Planet'] | None = Field('Planet', alias='__typename') + + + class Species(BaseModel): + class Config: + extra = Extra.allow + + average_height: String | None = None + average_lifespan: String | None = None + classification: String | None = None + designation: String | None = None + eye_colors: String | None = None + films: list[Film] + films_ids: list[ID] + hair_colors: String | None = None + id: ID + language: String | None = None + name: String + people: list[Person] + people_ids: list[ID] + skin_colors: String | None = None + typename__: Literal['Species'] | None = Field('Species', alias='__typename') + + + class Starship(BaseModel): + class Config: + extra = Extra.allow + + MGLT: String | None = None + cargo_capacity: String | None = None + consumables: String | None = None + cost_in_credits: String | None = None + crew: String | None = None + films: list[Film] + films_ids: list[ID] + hyperdrive_rating: String | None = None + id: ID + length: String | None = None + manufacturer: String | None = None + max_atmosphering_speed: String | None = None + model: String | None = None + name: String + passengers: String | None = None + pilots: list[Person] + pilots_ids: list[ID] + starship_class: String | None = None + typename__: Literal['Starship'] | None = Field('Starship', alias='__typename') + + + class Vehicle(BaseModel): + class Config: + extra = Extra.allow + + cargo_capacity: String | None = None + consumables: String | None = None + cost_in_credits: String | None = None + crew: String | None = None + films: list[Film] + films_ids: list[ID] + id: ID + length: String | None = None + manufacturer: String | None = None + max_atmosphering_speed: String | None = None + model: String | None = None + name: String + passengers: String | None = None + pilots: list[Person] + pilots_ids: list[ID] + vehicle_class: String | None = None + typename__: Literal['Vehicle'] | None = Field('Vehicle', alias='__typename') + + + Film.update_forward_refs() + Person.update_forward_refs() + ``` + +--- + +## `--field-constraints` {#field-constraints} + +Generate Field() with validation constraints from schema. + +The `--field-constraints` flag generates Pydantic Field() definitions with +validation constraints (min/max length, pattern, etc.) from the schema. +Output differs between Pydantic v1 and v2 due to API changes. + +**Related:** [`--strict-types`](typing-customization.md#strict-types) + +**See also:** [Field Constraints](../field-constraints.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --field-constraints # (1)! + ``` + + 1. :material-arrow-left: `--field-constraints` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + minimum: 0 + maximum: 100 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + minimum: 0 + maximum: 9223372036854775807 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + maxItems: 10 + minItems: 1 + uniqueItems: true + UID: + type: integer + minimum: 0 + Users: + type: array + items: + required: + - id + - name + - uid + properties: + id: + type: integer + format: int64 + minimum: 0 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + uid: + $ref: '#/components/schemas/UID' + phones: + type: array + items: + type: string + minLength: 3 + maxItems: 10 + fax: + type: array + items: + type: string + minLength: 3 + height: + type: + - integer + - number + minimum: 1 + maximum: 300 + weight: + type: + - number + - integer + minimum: 1.0 + maximum: 1000.0 + age: + type: integer + minimum: 0.0 + maximum: 200.0 + exclusiveMinimum: true + rating: + type: number + minimum: 0 + exclusiveMinimum: true + maximum: 5 + + Id: + type: string + Rules: + type: array + items: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: To be used as a dataset parameter value + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + minLength: 1 + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: api_constrained.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int = Field(..., ge=0, le=9223372036854775807) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + + + class Pets(BaseModel): + __root__: list[Pet] = Field(..., max_items=10, min_items=1, unique_items=True) + + + class UID(BaseModel): + __root__: int = Field(..., ge=0) + + + class Phone(BaseModel): + __root__: str = Field(..., min_length=3) + + + class FaxItem(BaseModel): + __root__: str = Field(..., min_length=3) + + + class User(BaseModel): + id: int = Field(..., ge=0) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + uid: UID + phones: list[Phone] | None = Field(None, max_items=10) + fax: list[FaxItem] | None = None + height: int | float | None = Field(None, ge=1.0, le=300.0) + weight: float | int | None = Field(None, ge=1.0, le=1000.0) + age: int | None = Field(None, gt=0, le=200) + rating: float | None = Field(None, gt=0.0, le=5.0) + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "Pydantic v2" + + ```python + # generated by datamodel-codegen: + # filename: api_constrained.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field, RootModel + + + class Pet(BaseModel): + id: int = Field(..., ge=0, le=9223372036854775807) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + + + class Pets(RootModel[list[Pet]]): + root: list[Pet] = Field(..., max_length=10, min_length=1) + + + class UID(RootModel[int]): + root: int = Field(..., ge=0) + + + class Phone(RootModel[str]): + root: str = Field(..., min_length=3) + + + class FaxItem(RootModel[str]): + root: str = Field(..., min_length=3) + + + class User(BaseModel): + id: int = Field(..., ge=0) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + uid: UID + phones: list[Phone] | None = Field(None, max_length=10) + fax: list[FaxItem] | None = None + height: int | float | None = Field(None, ge=1.0, le=300.0) + weight: float | int | None = Field(None, ge=1.0, le=1000.0) + age: int | None = Field(None, gt=0, le=200) + rating: float | None = Field(None, gt=0.0, le=5.0) + + + class Users(RootModel[list[User]]): + root: list[User] + + + class Id(RootModel[str]): + root: str + + + class Rules(RootModel[list[str]]): + root: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(RootModel[list[Api]]): + root: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "User", + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "ken" + }, + "age": { + "type": "integer" + }, + "salary": { + "type": "integer", + "minimum": 0 + }, + "debt" : { + "type": "integer", + "maximum": 0 + }, + "loan" : { + "type": "number", + "maximum": 0 + }, + "tel": { + "type": "string", + "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$" + }, + "height": { + "type": "number", + "minimum": 0 + }, + "weight": { + "type": "number", + "minimum": 0 + }, + "score": { + "type": "number", + "minimum": 1e-08 + }, + "active": { + "type": "boolean" + }, + "photo": { + "type": "string", + "format": "binary", + "minLength": 100 + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: strict_types.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import ( + BaseModel, + Field, + StrictBool, + StrictBytes, + StrictFloat, + StrictInt, + StrictStr, + ) + + + class User(BaseModel): + name: StrictStr | None = Field(None, example='ken') + age: StrictInt | None = None + salary: StrictInt | None = Field(None, ge=0) + debt: StrictInt | None = Field(None, le=0) + loan: StrictFloat | None = Field(None, le=0.0) + tel: StrictStr | None = Field(None, regex='^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$') + height: StrictFloat | None = Field(None, ge=0.0) + weight: StrictFloat | None = Field(None, ge=0.0) + score: StrictFloat | None = Field(None, ge=1e-08) + active: StrictBool | None = None + photo: StrictBytes | None = Field(None, min_length=100) + ``` + +--- + +## `--field-extra-keys` {#field-extra-keys} + +Include specific extra keys in Field() definitions. + +The `--field-extra-keys` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --field-extra-keys key2 --field-extra-keys-without-x-prefix x-repr # (1)! + ``` + + 1. :material-arrow-left: `--field-extra-keys` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Extras", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "normal key", + "key1": 123, + "key2": 456, + "$exclude": 123, + "invalid-key-1": "abc", + "-invalid+key_2": "efg", + "$comment": "comment", + "$id": "#name", + "register": "hij", + "schema": "klm", + "x-repr": true, + "x-abc": true, + "example": "example", + "readOnly": true + }, + "age": { + "type": "integer", + "example": 12, + "writeOnly": true, + "examples": [ + 13, + 20 + ] + }, + "status": { + "type": "string", + "examples": [ + "active" + ] + } + } + } + ``` + + **Output:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: extras.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Extras(BaseModel): + name: str | None = Field( + None, + description='normal key', + example='example', + invalid_key_1='abc', + key2=456, + repr=True, + ) + age: int | None = Field(None, example=12, examples=[13, 20]) + status: str | None = Field(None, examples=['active']) + ``` + + === "Pydantic v2" + + ```python + # generated by datamodel-codegen: + # filename: extras.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Extras(BaseModel): + name: str | None = Field( + None, + description='normal key', + examples=['example'], + json_schema_extra={'key2': 456, 'invalid-key-1': 'abc'}, + repr=True, + ) + age: int | None = Field(None, examples=[13, 20], json_schema_extra={'example': 12}) + status: str | None = Field(None, examples=['active']) + ``` + +--- + +## `--field-extra-keys-without-x-prefix` {#field-extra-keys-without-x-prefix} + +Include schema extension keys in Field() without requiring 'x-' prefix. + +The --field-extra-keys-without-x-prefix option allows you to specify custom +schema extension keys that should be included in Pydantic Field() extras without +the 'x-' prefix requirement. For example, 'x-repr' in the schema becomes 'repr' +in Field(). This is useful for custom schema extensions and vendor-specific metadata. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --field-include-all-keys --field-extra-keys-without-x-prefix x-repr # (1)! + ``` + + 1. :material-arrow-left: `--field-extra-keys-without-x-prefix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Extras", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "normal key", + "key1": 123, + "key2": 456, + "$exclude": 123, + "invalid-key-1": "abc", + "-invalid+key_2": "efg", + "$comment": "comment", + "$id": "#name", + "register": "hij", + "schema": "klm", + "x-repr": true, + "x-abc": true, + "example": "example", + "readOnly": true + }, + "age": { + "type": "integer", + "example": 12, + "writeOnly": true, + "examples": [ + 13, + 20 + ] + }, + "status": { + "type": "string", + "examples": [ + "active" + ] + } + } + } + ``` + + **Output:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: extras.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Extras(BaseModel): + name: str | None = Field( + None, + description='normal key', + example='example', + field_comment='comment', + field_exclude=123, + field_invalid_key_2='efg', + invalid_key_1='abc', + key1=123, + key2=456, + readOnly=True, + register_='hij', + repr=True, + schema_='klm', + x_abc=True, + ) + age: int | None = Field(None, example=12, examples=[13, 20], writeOnly=True) + status: str | None = Field(None, examples=['active']) + ``` + + === "Pydantic v2" + + ```python + # generated by datamodel-codegen: + # filename: extras.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Extras(BaseModel): + name: str | None = Field( + None, + description='normal key', + examples=['example'], + json_schema_extra={ + 'key1': 123, + 'key2': 456, + '$exclude': 123, + 'invalid-key-1': 'abc', + '-invalid+key_2': 'efg', + '$comment': 'comment', + 'register': 'hij', + 'schema': 'klm', + 'x-abc': True, + 'readOnly': True, + }, + repr=True, + ) + age: int | None = Field( + None, examples=[13, 20], json_schema_extra={'example': 12, 'writeOnly': True} + ) + status: str | None = Field(None, examples=['active']) + ``` + +--- + +## `--field-include-all-keys` {#field-include-all-keys} + +Include all schema keys in Field() json_schema_extra. + +The `--field-include-all-keys` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --field-include-all-keys # (1)! + ``` + + 1. :material-arrow-left: `--field-include-all-keys` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + ```python + # 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 = None + ``` + +--- + +## `--field-type-collision-strategy` {#field-type-collision-strategy} + +Rename type class instead of field when names collide (Pydantic v2 only). + +The `--field-type-collision-strategy` flag controls how field name and type name +collisions are resolved. With `rename-type`, the type class is renamed with a suffix +to preserve the original field name, instead of renaming the field and adding an alias. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --field-type-collision-strategy rename-type # (1)! + ``` + + 1. :material-arrow-left: `--field-type-collision-strategy` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "title": "Test", + "type": "object", + "properties": { + "TestObject": { + "title": "TestObject", + "type": "object", + "properties": { + "test_string": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: field_has_same_name.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class TestObject_1(BaseModel): + test_string: str | None = None + + + class Test(BaseModel): + TestObject: TestObject_1 | None = Field(None, title='TestObject') + ``` + +--- + +## `--no-alias` {#no-alias} + +Disable Field alias generation for non-Python-safe property names. + +The `--no-alias` flag disables automatic alias generation when JSON property +names contain characters invalid in Python (like hyphens). Without this flag, +fields are renamed to Python-safe names with `Field(alias='original-name')`. +With this flag, only Python-safe names are used without aliases. + +**See also:** [Field Aliases](../aliases.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --no-alias # (1)! + ``` + + 1. :material-arrow-left: `--no-alias` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "first-name": { + "type": "string" + }, + "last-name": { + "type": "string" + }, + "email_address": { + "type": "string" + } + }, + "required": ["first-name", "last-name"] + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: no_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Person(BaseModel): + first_name: str + last_name: str + email_address: str | None = None + ``` + + === "Without Option" + + ```python + # generated by datamodel-codegen: + # filename: no_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Person(BaseModel): + first_name: str = Field(..., alias='first-name') + last_name: str = Field(..., alias='last-name') + email_address: str | None = None + ``` + +--- + +## `--original-field-name-delimiter` {#original-field-name-delimiter} + +Specify delimiter for original field names when using snake-case conversion. + +The `--original-field-name-delimiter` option works with `--snake-case-field` to specify +the delimiter used in original field names. This is useful when field names contain +delimiters like spaces or hyphens that should be treated as word boundaries during +snake_case conversion. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --snake-case-field --original-field-name-delimiter " " # (1)! + ``` + + 1. :material-arrow-left: `--original-field-name-delimiter` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "SpaceIF": { + "$ref": "#/definitions/SpaceIF" + } + }, + "definitions": { + "SpaceIF": { + "type": "string", + "enum": [ + "Space Field" + ] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: space_field_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel, Field + + + class SpaceIF(Enum): + space_field = 'Space Field' + + + class Model(BaseModel): + space_if: SpaceIF | None = Field(None, alias='SpaceIF') + ``` + +--- + +## `--remove-special-field-name-prefix` {#remove-special-field-name-prefix} + +Remove the special prefix from field names. + +The `--remove-special-field-name-prefix` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --remove-special-field-name-prefix # (1)! + ``` + + 1. :material-arrow-left: `--remove-special-field-name-prefix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$id": "schema_v2.json", + "$schema": "http://json-schema.org/schema#", + + "type": "object", + "properties": { + "@id": { + "type": "string", + "format": "uri", + "pattern": "^http.*$", + "title": "Id must be presesnt and must be a URI" + }, + "@type": { "type": "string" }, + "@+!type": { "type": "string" }, + "@-!type": { "type": "string" }, + "profile": { "type": "string" } + }, + "required": ["@id", "@type"] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: special_prefix_model.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Model(BaseModel): + id: AnyUrl = Field(..., alias='@id', title='Id must be presesnt and must be a URI') + type: str = Field(..., alias='@type') + type_1: str | None = Field(None, alias='@+!type') + type_2: str | None = Field(None, alias='@-!type') + profile: str | None = None + ``` + +--- + +## `--set-default-enum-member` {#set-default-enum-member} + +Set the first enum member as the default value for enum fields. + +The `--set-default-enum-member` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --reuse-model --set-default-enum-member # (1)! + ``` + + 1. :material-arrow-left: `--set-default-enum-member` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # 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 + + + class Animal(Enum): + dog = 'dog' + cat = 'cat' + snake = 'snake' + + + class RedistributeEnum(Enum): + static = 'static' + connected = 'connected' + + + class User(BaseModel): + name: str | None = None + animal: Animal | None = Animal.dog + pet: Animal | None = Animal.cat + redistribute: list[RedistributeEnum] | None = None + + + class Redistribute(BaseModel): + __root__: list[RedistributeEnum] = Field( + ..., description='Redistribute type for routes.' + ) + ``` + +--- + +## `--snake-case-field` {#snake-case-field} + +Convert field names to snake_case format. + +The `--snake-case-field` flag converts camelCase or PascalCase field names +to snake_case format in the generated Python code, following Python naming +conventions (PEP 8). + +**Related:** [`--capitalize-enum-members`](field-customization.md#capitalize-enum-members) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --snake-case-field # (1)! + ``` + + 1. :material-arrow-left: `--snake-case-field` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InvalidEnum", + "type": "string", + "enum": [ + "1 value", + " space", + "*- special", + "schema", + "MRO", + "mro" + ] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: invalid_enum_name.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + + class InvalidEnum(Enum): + field_1_value = '1 value' + field_space = ' space' + field___special = '*- special' + schema = 'schema' + mro_1 = 'MRO' + mro_ = 'mro' + ``` + +--- + +## `--special-field-name-prefix` {#special-field-name-prefix} + +Prefix to add to special field names (like reserved keywords). + +The `--special-field-name-prefix` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --special-field-name-prefix special # (1)! + ``` + + 1. :material-arrow-left: `--special-field-name-prefix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "string", + "enum": [ + true, + false, + "", + "\n", + "\r\n", + "\t", + "\\x08", + null, + "\\" + ] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: special_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel + + + class ModelEnum(Enum): + True_ = True + False_ = False + special_ = '' + special__1 = '\n' + special__ = '\r\n' + special__2 = '\t' + special_x08 = '\\x08' + special__3 = '\\' + + + class Model(BaseModel): + __root__: ModelEnum | None = None + ``` + +--- + +## `--use-attribute-docstrings` {#use-attribute-docstrings} + +Generate field descriptions as attribute docstrings instead of Field descriptions. + +The `--use-attribute-docstrings` flag places field descriptions in Python docstring +format (PEP 224 attribute docstrings) rather than in Field(..., description=...). +This provides better IDE support for hovering over attributes. Requires +`--use-field-description` to be enabled. + +**Related:** [`--use-field-description`](field-customization.md#use-field-description) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --use-field-description --use-attribute-docstrings # (1)! + ``` + + 1. :material-arrow-left: `--use-attribute-docstrings` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "Person", + "properties": { + "name": { + "type": "string", + "description": "The person's full name" + }, + "age": { + "type": "integer", + "description": "The person's age in years" + } + }, + "required": ["name"] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: use_attribute_docstrings_test.json + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, ConfigDict + + + class Person(BaseModel): + model_config = ConfigDict( + use_attribute_docstrings=True, + ) + name: str + """ + The person's full name + """ + age: int | None = None + """ + The person's age in years + """ + ``` + +--- + +## `--use-enum-values-in-discriminator` {#use-enum-values-in-discriminator} + +Use enum values in discriminator mappings for union types. + +The `--use-enum-values-in-discriminator` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-enum-values-in-discriminator --output-model-type pydantic_v2.BaseModel # (1)! + ``` + + 1. :material-arrow-left: `--use-enum-values-in-discriminator` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + components: + schemas: + Request: + oneOf: + - $ref: '#/components/schemas/RequestV1' + - $ref: '#/components/schemas/RequestV2' + discriminator: + propertyName: version + mapping: + v1: '#/components/schemas/RequestV1' + v2: '#/components/schemas/RequestV2' + + RequestVersionEnum: + type: string + description: this is not included! + title: no title! + enum: + - v1 + - v2 + RequestBase: + properties: + version: + $ref: '#/components/schemas/RequestVersionEnum' + required: + - version + + RequestV1: + allOf: + - $ref: '#/components/schemas/RequestBase' + properties: + request_id: + type: string + title: test title + description: there is description + required: + - request_id + RequestV2: + allOf: + - $ref: '#/components/schemas/RequestBase' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: discriminator_enum.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + from typing import Literal + + from pydantic import BaseModel, Field, RootModel + + + class RequestVersionEnum(Enum): + v1 = 'v1' + v2 = 'v2' + + + class RequestBase(BaseModel): + version: RequestVersionEnum + + + class RequestV1(RequestBase): + request_id: str = Field(..., description='there is description', title='test title') + version: Literal[RequestVersionEnum.v1] + + + class RequestV2(RequestBase): + version: Literal[RequestVersionEnum.v2] + + + class Request(RootModel[RequestV1 | RequestV2]): + root: RequestV1 | RequestV2 = Field(..., discriminator='version') + ``` + +--- + +## `--use-field-description` {#use-field-description} + +Include schema descriptions as Field docstrings. + +The `--use-field-description` flag extracts the `description` property from +schema fields and includes them as docstrings or Field descriptions in the +generated models, preserving documentation from the original schema. + +**Related:** [`--use-inline-field-description`](field-customization.md#use-inline-field-description), [`--use-schema-description`](field-customization.md#use-schema-description) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-type-alias --use-field-description # (1)! + ``` + + 1. :material-arrow-left: `--use-field-description` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + default: 1 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Users: + type: array + items: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Id: + type: string + Rules: + type: array + items: + type: string + Error: + description: "error result.\nNow with multi-line docstrings." + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: "To be used as a dataset parameter value.\nNow also with multi-line docstrings." + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + description: Event object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: api_multiline_docstrings.yaml + # timestamp: 2022-11-11T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = None + """ + To be used as a dataset parameter value. + Now also with multi-line docstrings. + """ + apiVersionNumber: str | None = None + """ + To be used as a version parameter value + """ + apiUrl: AnyUrl | None = None + """ + The URL describing the dataset's fields + """ + apiDocumentationUrl: AnyUrl | None = None + """ + A URL to the API console for each API + """ + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "SimpleString": { + "type": "string" + }, + "UnionType": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"} + ] + }, + "ArrayType": { + "type": "array", + "items": {"type": "string"} + }, + "AnnotatedType": { + "title": "MyAnnotatedType", + "description": "An annotated union type", + "anyOf": [ + {"type": "string"}, + {"type": "boolean"} + ] + }, + "ModelWithTypeAliasField": { + "type": "object", + "properties": { + "simple_field": {"$ref": "#/definitions/SimpleString"}, + "union_field": {"$ref": "#/definitions/UnionType"}, + "array_field": {"$ref": "#/definitions/ArrayType"}, + "annotated_field": {"$ref": "#/definitions/AnnotatedType"} + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: type_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated, Any, TypeAlias + + from pydantic import BaseModel, Field + + Model: TypeAlias = Any + + + SimpleString: TypeAlias = str + + + UnionType: TypeAlias = str | int + + + ArrayType: TypeAlias = list[str] + + + AnnotatedType: TypeAlias = Annotated[str | bool, Field(..., title='MyAnnotatedType')] + """ + An annotated union type + """ + + + class ModelWithTypeAliasField(BaseModel): + simple_field: SimpleString | None = None + union_field: UnionType | None = None + array_field: ArrayType | None = None + annotated_field: AnnotatedType | None = None + ``` + +--- + +## `--use-field-description-example` {#use-field-description-example} + +Add field examples to docstrings. + +The `--use-field-description-example` flag adds the `example` or `examples` +property from schema fields as docstrings. This provides documentation that +is visible in IDE intellisense. + +**Related:** [`--use-field-description`](field-customization.md#use-field-description), [`--use-inline-field-description`](field-customization.md#use-inline-field-description) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-field-description-example # (1)! + ``` + + 1. :material-arrow-left: `--use-field-description-example` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Extras", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "normal key", + "key1": 123, + "key2": 456, + "$exclude": 123, + "invalid-key-1": "abc", + "-invalid+key_2": "efg", + "$comment": "comment", + "$id": "#name", + "register": "hij", + "schema": "klm", + "x-repr": true, + "x-abc": true, + "example": "example", + "readOnly": true + }, + "age": { + "type": "integer", + "example": 12, + "writeOnly": true, + "examples": [ + 13, + 20 + ] + }, + "status": { + "type": "string", + "examples": [ + "active" + ] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: extras.json + # timestamp: 2022-11-11T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Extras(BaseModel): + name: str | None = Field(None, description='normal key', example='example') + """ + Example: 'example' + """ + age: int | None = Field(None, example=12, examples=[13, 20]) + """ + Examples: + - 13 + - 20 + """ + status: str | None = Field(None, examples=['active']) + """ + Example: 'active' + """ + ``` + +--- + +## `--use-inline-field-description` {#use-inline-field-description} + +Add field descriptions as inline comments. + +The `--use-inline-field-description` flag adds the `description` property from +schema fields as inline comments after each field definition. This provides +documentation without using Field() wrappers. + +**Related:** [`--use-field-description`](field-customization.md#use-field-description), [`--use-schema-description`](field-customization.md#use-schema-description) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-inline-field-description # (1)! + ``` + + 1. :material-arrow-left: `--use-inline-field-description` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + default: 1 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Users: + type: array + items: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Id: + type: string + Rules: + type: array + items: + type: string + Error: + description: "error result.\nNow with multi-line docstrings." + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: "To be used as a dataset parameter value.\nNow also with multi-line docstrings." + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + description: Event object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: api_multiline_docstrings.yaml + # timestamp: 2022-11-11T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, + description='To be used as a dataset parameter value.\nNow also with multi-line docstrings.', + ) + """ + To be used as a dataset parameter value. + Now also with multi-line docstrings. + """ + + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + """To be used as a version parameter value""" + + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + """The URL describing the dataset's fields""" + + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + """A URL to the API console for each API""" + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MultilineDescriptionWithExample", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name.\nThis is a multi-line description.", + "example": "John Doe" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: multiline_description_with_example.json + # timestamp: 2022-11-11T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class MultilineDescriptionWithExample(BaseModel): + name: str | None = Field( + None, + description='User name.\nThis is a multi-line description.', + example='John Doe', + ) + """ + User name. + This is a multi-line description. + + Example: 'John Doe' + """ + ``` + +--- + +## `--use-schema-description` {#use-schema-description} + +Use schema description as class docstring. + +The `--use-schema-description` flag extracts the `description` property from +schema definitions and adds it as a docstring to the generated class. This is +useful for preserving documentation from your schema in the generated code. + +**Related:** [`--use-field-description`](field-customization.md#use-field-description), [`--use-inline-field-description`](field-customization.md#use-inline-field-description) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-schema-description # (1)! + ``` + + 1. :material-arrow-left: `--use-schema-description` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + default: 1 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Users: + type: array + items: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Id: + type: string + Rules: + type: array + items: + type: string + Error: + description: "error result.\nNow with multi-line docstrings." + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: "To be used as a dataset parameter value.\nNow also with multi-line docstrings." + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + description: Event object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: api_multiline_docstrings.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + """ + error result. + Now with multi-line docstrings. + """ + + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, + description='To be used as a dataset parameter value.\nNow also with multi-line docstrings.', + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + """ + Event object + """ + + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--use-serialization-alias` {#use-serialization-alias} + +Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). + +The `--use-serialization-alias` flag changes field aliasing to use `serialization_alias` +instead of `alias`. This allows setting values using the Pythonic field name while +serializing to the original JSON property name. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-serialization-alias --output-model-type pydantic_v2.BaseModel # (1)! + ``` + + 1. :material-arrow-left: `--use-serialization-alias` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "first-name": { + "type": "string" + }, + "last-name": { + "type": "string" + }, + "email_address": { + "type": "string" + } + }, + "required": ["first-name", "last-name"] + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: no_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Person(BaseModel): + first_name: str = Field(..., serialization_alias='first-name') + last_name: str = Field(..., serialization_alias='last-name') + email_address: str | None = None + ``` + + === "Without Option" + + ```python + # generated by datamodel-codegen: + # filename: no_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Person(BaseModel): + first_name: str = Field(..., alias='first-name') + last_name: str = Field(..., alias='last-name') + email_address: str | None = None + ``` + +--- + +## `--use-title-as-name` {#use-title-as-name} + +Use schema title as the generated class name. + +The `--use-title-as-name` flag uses the `title` property from the schema +as the class name instead of deriving it from the property name or path. +This is useful when schemas have descriptive titles that should be preserved. + +**Related:** [`--class-name`](model-customization.md#class-name) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-title-as-name # (1)! + ``` + + 1. :material-arrow-left: `--use-title-as-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "ProcessingStatus": { + "title": "Processing Status Title", + "enum": [ + "COMPLETED", + "PENDING", + "FAILED" + ], + "type": "string", + "description": "The processing status" + }, + "kind": { + "type": "string" + }, + "ExtendedProcessingTask": { + "title": "Extended Processing Task Title", + "oneOf": [ + { + "$ref": "#" + }, + { + "type": "object", + "title": "NestedCommentTitle", + "properties": { + "comment": { + "type": "string" + } + } + } + ] + }, + "ExtendedProcessingTasks": { + "title": "Extended Processing Tasks Title", + "type": "array", + "items": [ + { + "$ref": "#/definitions/ExtendedProcessingTask" + } + ] + }, + "ProcessingTask": { + "title": "Processing Task Title", + "type": "object", + "properties": { + "processing_status_union": { + "title": "Processing Status Union Title", + "oneOf": [ + { + "title": "Processing Status Detail", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "description": { + "type": "string" + } + } + }, + { + "$ref": "#/definitions/ExtendedProcessingTask" + }, + { + "$ref": "#/definitions/ProcessingStatus" + } + ], + "default": "COMPLETED" + }, + "processing_status": { + "$ref": "#/definitions/ProcessingStatus", + "default": "COMPLETED" + }, + "name": { + "type": "string" + }, + "kind": { + "$ref": "#/definitions/kind" + } + } + } + }, + "title": "Processing Tasks Title", + "type": "array", + "items": [ + { + "$ref": "#/definitions/ProcessingTask" + } + ] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: titles.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel, Field + + + class ProcessingStatusTitle(Enum): + COMPLETED = 'COMPLETED' + PENDING = 'PENDING' + FAILED = 'FAILED' + + + class Kind(BaseModel): + __root__: str + + + class NestedCommentTitle(BaseModel): + comment: str | None = None + + + class ProcessingStatusDetail(BaseModel): + id: int | None = None + description: str | None = None + + + class ProcessingTasksTitle(BaseModel): + __root__: list[ProcessingTaskTitle] = Field(..., title='Processing Tasks Title') + + + class ExtendedProcessingTask(BaseModel): + __root__: ProcessingTasksTitle | NestedCommentTitle = Field( + ..., title='Extended Processing Task Title' + ) + + + class ExtendedProcessingTasksTitle(BaseModel): + __root__: list[ExtendedProcessingTask] = Field( + ..., title='Extended Processing Tasks Title' + ) + + + class ProcessingStatusUnionTitle(BaseModel): + __root__: ( + ProcessingStatusDetail | ExtendedProcessingTask | ProcessingStatusTitle + ) = Field(..., title='Processing Status Union Title') + + + class ProcessingTaskTitle(BaseModel): + processing_status_union: ProcessingStatusUnionTitle | None = Field( + default_factory=lambda: ProcessingStatusUnionTitle.parse_obj('COMPLETED'), + title='Processing Status Union Title', + ) + processing_status: ProcessingStatusTitle | None = 'COMPLETED' + name: str | None = None + kind: Kind | None = None + + + ProcessingTasksTitle.update_forward_refs() + ``` + +--- + +--- + +# Typing Customization + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/typing-customization/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--allof-class-hierarchy`](#allof-class-hierarchy) | Controls how allOf schemas are represented in the generated ... | +| [`--allof-merge-mode`](#allof-merge-mode) | Merge constraints from root model references in allOf schema... | +| [`--disable-future-imports`](#disable-future-imports) | Prevent automatic addition of __future__ imports in generate... | +| [`--enum-field-as-literal`](#enum-field-as-literal) | Convert all enum fields to Literal types instead of Enum cla... | +| [`--enum-field-as-literal-map`](#enum-field-as-literal-map) | Override enum/literal generation per-field via JSON mapping.... | +| [`--ignore-enum-constraints`](#ignore-enum-constraints) | Ignore enum constraints and use base string type instead of ... | +| [`--no-use-specialized-enum`](#no-use-specialized-enum) | Disable specialized Enum classes for Python 3.11+ code gener... | +| [`--no-use-standard-collections`](#no-use-standard-collections) | Use typing.Dict/List instead of built-in dict/list for conta... | +| [`--no-use-union-operator`](#no-use-union-operator) | Use Union[X, Y] / Optional[X] instead of X | Y union operato... | +| [`--output-date-class`](#output-date-class) | Specify date class type for date schema fields. | +| [`--output-datetime-class`](#output-datetime-class) | Specify datetime class type for date-time schema fields. | +| [`--strict-types`](#strict-types) | Enable strict type validation for specified Python types. | +| [`--type-mappings`](#type-mappings) | Override default type mappings for schema formats. | +| [`--type-overrides`](#type-overrides) | Replace schema model types with custom Python types via JSON... | +| [`--use-annotated`](#use-annotated) | Use typing.Annotated for Field() with constraints. | +| [`--use-decimal-for-multiple-of`](#use-decimal-for-multiple-of) | Generate Decimal types for fields with multipleOf constraint... | +| [`--use-generic-container-types`](#use-generic-container-types) | Use generic container types (Sequence, Mapping) for type hin... | +| [`--use-non-positive-negative-number-constrained-types`](#use-non-positive-negative-number-constrained-types) | Use NonPositive/NonNegative types for number constraints. | +| [`--use-pendulum`](#use-pendulum) | Use pendulum types for date/time fields instead of datetime ... | +| [`--use-root-model-type-alias`](#use-root-model-type-alias) | Generate RootModel as type alias format for better mypy supp... | +| [`--use-specialized-enum`](#use-specialized-enum) | Generate StrEnum/IntEnum for string/integer enums (Python 3.... | +| [`--use-standard-collections`](#use-standard-collections) | Use built-in dict/list instead of typing.Dict/List. | +| [`--use-standard-primitive-types`](#use-standard-primitive-types) | Use Python standard library types for string formats instead... | +| [`--use-tuple-for-fixed-items`](#use-tuple-for-fixed-items) | Generate tuple types for arrays with items array syntax. | +| [`--use-type-alias`](#use-type-alias) | Use TypeAlias instead of root models for type definitions (e... | +| [`--use-union-operator`](#use-union-operator) | Use | operator for Union types (PEP 604). | +| [`--use-unique-items-as-set`](#use-unique-items-as-set) | Generate set types for arrays with uniqueItems constraint. | + +--- + +## `--allof-class-hierarchy` {#allof-class-hierarchy} + +Controls how allOf schemas are represented in the generated class hierarchy. +`--allof-class-hierarchy if-no-conflict` (default) creates parent classes for allOf schemas +only when there are no property conflicts between parent schemas. Otherwise, properties are merged into the child class +which is then decoupled from the parent classes and no longer inherits from them. +`--allof-class-hierarchy always` keeps class hierarchy for allOf schemas, +even in multiple inheritance scenarios where two parent schemas define the same property. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --allof-class-hierarchy always # (1)! + ``` + + 1. :material-arrow-left: `--allof-class-hierarchy` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "StringDatatype": { + "description": "A base string type.", + "type": "string", + "pattern": "^\\S(.*\\S)?$" + }, + "ConstrainedStringDatatype": { + "description": "A constrained string.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "type": "string", "minLength": 1, "pattern": "^[A-Z].*" } + ] + }, + "IntegerDatatype": { + "description": "A whole number.", + "type": "integer" + }, + "NonNegativeIntegerDatatype": { + "description": "Non-negative integer.", + "allOf": [ + { "$ref": "#/definitions/IntegerDatatype" }, + { "minimum": 0 } + ] + }, + "BoundedIntegerDatatype": { + "description": "Integer between 0 and 100.", + "allOf": [ + { "$ref": "#/definitions/IntegerDatatype" }, + { "minimum": 0, "maximum": 100 } + ] + }, + "EmailDatatype": { + "description": "Email with format.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "format": "email" } + ] + }, + "FormattedStringDatatype": { + "description": "A string with email format.", + "type": "string", + "format": "email" + }, + "ObjectBase": { + "type": "object", + "properties": { + "id": { "type": "integer" } + } + }, + "ObjectWithAllOf": { + "description": "Object inheritance - not a root model.", + "allOf": [ + { "$ref": "#/definitions/ObjectBase" }, + { "type": "object", "properties": { "name": { "type": "string" } } } + ] + }, + "MultiRefAllOf": { + "description": "Multiple refs - not handled by new code.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "$ref": "#/definitions/IntegerDatatype" } + ] + }, + "NoConstraintAllOf": { + "description": "No constraints added.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" } + ] + }, + "IncompatibleTypeAllOf": { + "description": "Incompatible types.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "type": "boolean" } + ] + }, + "ConstraintWithProperties": { + "description": "Constraint item has properties.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "properties": { "extra": { "type": "string" } } } + ] + }, + "ConstraintWithItems": { + "description": "Constraint item has items.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "items": { "type": "string" } } + ] + }, + "NumberIntegerCompatible": { + "description": "Number and integer are compatible.", + "allOf": [ + { "$ref": "#/definitions/IntegerDatatype" }, + { "type": "number", "minimum": 0 } + ] + }, + "RefWithSchemaKeywords": { + "description": "Ref with additional schema keywords.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype", "minLength": 5 }, + { "maxLength": 100 } + ] + }, + "ArrayDatatype": { + "type": "array", + "items": { "type": "string" } + }, + "RefToArrayAllOf": { + "description": "Ref to array - not a root model.", + "allOf": [ + { "$ref": "#/definitions/ArrayDatatype" }, + { "minItems": 1 } + ] + }, + "ObjectNoPropsDatatype": { + "type": "object" + }, + "RefToObjectNoPropsAllOf": { + "description": "Ref to object without properties - not a root model.", + "allOf": [ + { "$ref": "#/definitions/ObjectNoPropsDatatype" }, + { "minProperties": 1 } + ] + }, + "PatternPropsDatatype": { + "patternProperties": { + "^S_": { "type": "string" } + } + }, + "RefToPatternPropsAllOf": { + "description": "Ref to patternProperties - not a root model.", + "allOf": [ + { "$ref": "#/definitions/PatternPropsDatatype" }, + { "minProperties": 1 } + ] + }, + "NestedAllOfDatatype": { + "allOf": [ + { "type": "string" }, + { "minLength": 1 } + ] + }, + "RefToNestedAllOfAllOf": { + "description": "Ref to nested allOf - not a root model.", + "allOf": [ + { "$ref": "#/definitions/NestedAllOfDatatype" }, + { "maxLength": 100 } + ] + }, + "ConstraintsOnlyDatatype": { + "description": "Constraints only, no type.", + "minLength": 1, + "pattern": "^[A-Z]" + }, + "RefToConstraintsOnlyAllOf": { + "description": "Ref to constraints-only schema.", + "allOf": [ + { "$ref": "#/definitions/ConstraintsOnlyDatatype" }, + { "maxLength": 100 } + ] + }, + "NoDescriptionAllOf": { + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "minLength": 5 } + ] + }, + "EmptyConstraintItemAllOf": { + "description": "AllOf with empty constraint item.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + {}, + { "maxLength": 50 } + ] + }, + "ConflictingFormatAllOf": { + "description": "Conflicting formats - falls back to existing behavior.", + "allOf": [ + { "$ref": "#/definitions/FormattedStringDatatype" }, + { "format": "date-time" } + ] + } + }, + "type": "object", + "properties": { + "name": { "$ref": "#/definitions/ConstrainedStringDatatype" }, + "count": { "$ref": "#/definitions/NonNegativeIntegerDatatype" }, + "percentage": { "$ref": "#/definitions/BoundedIntegerDatatype" }, + "email": { "$ref": "#/definitions/EmailDatatype" }, + "obj": { "$ref": "#/definitions/ObjectWithAllOf" }, + "multi": { "$ref": "#/definitions/MultiRefAllOf" }, + "noconstraint": { "$ref": "#/definitions/NoConstraintAllOf" }, + "incompatible": { "$ref": "#/definitions/IncompatibleTypeAllOf" }, + "withprops": { "$ref": "#/definitions/ConstraintWithProperties" }, + "withitems": { "$ref": "#/definitions/ConstraintWithItems" }, + "numint": { "$ref": "#/definitions/NumberIntegerCompatible" }, + "refwithkw": { "$ref": "#/definitions/RefWithSchemaKeywords" }, + "refarr": { "$ref": "#/definitions/RefToArrayAllOf" }, + "refobjnoprops": { "$ref": "#/definitions/RefToObjectNoPropsAllOf" }, + "refpatternprops": { "$ref": "#/definitions/RefToPatternPropsAllOf" }, + "refnestedallof": { "$ref": "#/definitions/RefToNestedAllOfAllOf" }, + "refconstraintsonly": { "$ref": "#/definitions/RefToConstraintsOnlyAllOf" }, + "nodescription": { "$ref": "#/definitions/NoDescriptionAllOf" }, + "emptyconstraint": { "$ref": "#/definitions/EmptyConstraintItemAllOf" }, + "conflictingformat": { "$ref": "#/definitions/ConflictingFormatAllOf" } + } + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: allof_class_hierarchy.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field, constr + + + class Entity(BaseModel): + type: str + type_list: list[str] | None = ['playground:Entity'] + + + class Entity2(BaseModel): + type: str + type_list: list[str] + + + class Thing(Entity): + type: str | None = 'playground:Thing' + type_list: list[str] | None = ['playground:Thing'] + name: constr(min_length=1) = Field(..., description='The things name') + + + class Location(Entity2): + type: str | None = 'playground:Location' + type_list: list[str] | None = ['playground:Location'] + address: constr(min_length=5) = Field( + ..., description='The address of the location' + ) + + + class Person(Thing, Location): + name: constr(min_length=1) | None = Field(None, description="The person's name") + type: str | None = 'playground:Person' + type_list: list[str] | None = ['playground:Person'] + ``` + + === "Without Option" + + ```python + # generated by datamodel-codegen: + # filename: allof_class_hierarchy.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel, Field, constr + + + class Person(BaseModel): + name: constr(min_length=1) = Field(..., description='The things name') + type: Any | None = 'playground:Location' + type_list: list[Any] | None = [ + 'playground:Person', + 'playground:Thing', + 'playground:Location', + ] + address: constr(min_length=5) = Field( + ..., description='The address of the location' + ) + + + class Entity(BaseModel): + type: str + type_list: list[str] | None = ['playground:Entity'] + + + class Entity2(BaseModel): + type: str + type_list: list[str] + + + class Thing(Entity): + type: str | None = 'playground:Thing' + type_list: list[str] | None = ['playground:Thing'] + name: constr(min_length=1) = Field(..., description='The things name') + + + class Location(Entity2): + type: str | None = 'playground:Location' + type_list: list[str] | None = ['playground:Location'] + address: constr(min_length=5) = Field( + ..., description='The address of the location' + ) + ``` + +--- + +## `--allof-merge-mode` {#allof-merge-mode} + +Merge constraints from root model references in allOf schemas. + +The `--allof-merge-mode constraints` merges only constraint properties +(minLength, maximum, etc.) from parent schemas referenced in allOf. +This ensures child schemas inherit validation constraints while keeping +other properties separate. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --allof-merge-mode constraints # (1)! + ``` + + 1. :material-arrow-left: `--allof-merge-mode` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + title: Test materialize allOf defaults + version: "1.0.0" + components: + schemas: + Parent: + type: object + properties: + name: + type: string + default: "parent_default" + minLength: 1 + count: + type: integer + default: 10 + minimum: 0 + Child: + allOf: + - $ref: "#/components/schemas/Parent" + - type: object + properties: + name: + maxLength: 100 + count: + maximum: 1000 + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: allof_materialize_defaults.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, conint, constr + + + class Parent(BaseModel): + name: constr(min_length=1) | None = 'parent_default' + count: conint(ge=0) | None = 10 + + + class Child(Parent): + name: constr(min_length=1, max_length=100) | None = 'parent_default' + count: conint(ge=0, le=1000) | None = 10 + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "StringDatatype": { + "description": "A base string type.", + "type": "string", + "pattern": "^\\S(.*\\S)?$" + }, + "ConstrainedStringDatatype": { + "description": "A constrained string.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "type": "string", "minLength": 1, "pattern": "^[A-Z].*" } + ] + }, + "IntegerDatatype": { + "description": "A whole number.", + "type": "integer" + }, + "NonNegativeIntegerDatatype": { + "description": "Non-negative integer.", + "allOf": [ + { "$ref": "#/definitions/IntegerDatatype" }, + { "minimum": 0 } + ] + }, + "BoundedIntegerDatatype": { + "description": "Integer between 0 and 100.", + "allOf": [ + { "$ref": "#/definitions/IntegerDatatype" }, + { "minimum": 0, "maximum": 100 } + ] + }, + "EmailDatatype": { + "description": "Email with format.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "format": "email" } + ] + }, + "FormattedStringDatatype": { + "description": "A string with email format.", + "type": "string", + "format": "email" + }, + "ObjectBase": { + "type": "object", + "properties": { + "id": { "type": "integer" } + } + }, + "ObjectWithAllOf": { + "description": "Object inheritance - not a root model.", + "allOf": [ + { "$ref": "#/definitions/ObjectBase" }, + { "type": "object", "properties": { "name": { "type": "string" } } } + ] + }, + "MultiRefAllOf": { + "description": "Multiple refs - not handled by new code.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "$ref": "#/definitions/IntegerDatatype" } + ] + }, + "NoConstraintAllOf": { + "description": "No constraints added.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" } + ] + }, + "IncompatibleTypeAllOf": { + "description": "Incompatible types.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "type": "boolean" } + ] + }, + "ConstraintWithProperties": { + "description": "Constraint item has properties.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "properties": { "extra": { "type": "string" } } } + ] + }, + "ConstraintWithItems": { + "description": "Constraint item has items.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "items": { "type": "string" } } + ] + }, + "NumberIntegerCompatible": { + "description": "Number and integer are compatible.", + "allOf": [ + { "$ref": "#/definitions/IntegerDatatype" }, + { "type": "number", "minimum": 0 } + ] + }, + "RefWithSchemaKeywords": { + "description": "Ref with additional schema keywords.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype", "minLength": 5 }, + { "maxLength": 100 } + ] + }, + "ArrayDatatype": { + "type": "array", + "items": { "type": "string" } + }, + "RefToArrayAllOf": { + "description": "Ref to array - not a root model.", + "allOf": [ + { "$ref": "#/definitions/ArrayDatatype" }, + { "minItems": 1 } + ] + }, + "ObjectNoPropsDatatype": { + "type": "object" + }, + "RefToObjectNoPropsAllOf": { + "description": "Ref to object without properties - not a root model.", + "allOf": [ + { "$ref": "#/definitions/ObjectNoPropsDatatype" }, + { "minProperties": 1 } + ] + }, + "PatternPropsDatatype": { + "patternProperties": { + "^S_": { "type": "string" } + } + }, + "RefToPatternPropsAllOf": { + "description": "Ref to patternProperties - not a root model.", + "allOf": [ + { "$ref": "#/definitions/PatternPropsDatatype" }, + { "minProperties": 1 } + ] + }, + "NestedAllOfDatatype": { + "allOf": [ + { "type": "string" }, + { "minLength": 1 } + ] + }, + "RefToNestedAllOfAllOf": { + "description": "Ref to nested allOf - not a root model.", + "allOf": [ + { "$ref": "#/definitions/NestedAllOfDatatype" }, + { "maxLength": 100 } + ] + }, + "ConstraintsOnlyDatatype": { + "description": "Constraints only, no type.", + "minLength": 1, + "pattern": "^[A-Z]" + }, + "RefToConstraintsOnlyAllOf": { + "description": "Ref to constraints-only schema.", + "allOf": [ + { "$ref": "#/definitions/ConstraintsOnlyDatatype" }, + { "maxLength": 100 } + ] + }, + "NoDescriptionAllOf": { + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + { "minLength": 5 } + ] + }, + "EmptyConstraintItemAllOf": { + "description": "AllOf with empty constraint item.", + "allOf": [ + { "$ref": "#/definitions/StringDatatype" }, + {}, + { "maxLength": 50 } + ] + }, + "ConflictingFormatAllOf": { + "description": "Conflicting formats - falls back to existing behavior.", + "allOf": [ + { "$ref": "#/definitions/FormattedStringDatatype" }, + { "format": "date-time" } + ] + } + }, + "type": "object", + "properties": { + "name": { "$ref": "#/definitions/ConstrainedStringDatatype" }, + "count": { "$ref": "#/definitions/NonNegativeIntegerDatatype" }, + "percentage": { "$ref": "#/definitions/BoundedIntegerDatatype" }, + "email": { "$ref": "#/definitions/EmailDatatype" }, + "obj": { "$ref": "#/definitions/ObjectWithAllOf" }, + "multi": { "$ref": "#/definitions/MultiRefAllOf" }, + "noconstraint": { "$ref": "#/definitions/NoConstraintAllOf" }, + "incompatible": { "$ref": "#/definitions/IncompatibleTypeAllOf" }, + "withprops": { "$ref": "#/definitions/ConstraintWithProperties" }, + "withitems": { "$ref": "#/definitions/ConstraintWithItems" }, + "numint": { "$ref": "#/definitions/NumberIntegerCompatible" }, + "refwithkw": { "$ref": "#/definitions/RefWithSchemaKeywords" }, + "refarr": { "$ref": "#/definitions/RefToArrayAllOf" }, + "refobjnoprops": { "$ref": "#/definitions/RefToObjectNoPropsAllOf" }, + "refpatternprops": { "$ref": "#/definitions/RefToPatternPropsAllOf" }, + "refnestedallof": { "$ref": "#/definitions/RefToNestedAllOfAllOf" }, + "refconstraintsonly": { "$ref": "#/definitions/RefToConstraintsOnlyAllOf" }, + "nodescription": { "$ref": "#/definitions/NoDescriptionAllOf" }, + "emptyconstraint": { "$ref": "#/definitions/EmptyConstraintItemAllOf" }, + "conflictingformat": { "$ref": "#/definitions/ConflictingFormatAllOf" } + } + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: allof_root_model_constraints.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel, EmailStr, Field, conint, constr + + + class StringDatatype(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$') = Field( + ..., description='A base string type.' + ) + + + class ConstrainedStringDatatype(BaseModel): + __root__: constr(regex=r'(?=^\S(.*\S)?$)(?=^[A-Z].*)', min_length=1) = Field( + ..., description='A constrained string.' + ) + + + class IntegerDatatype(BaseModel): + __root__: int = Field(..., description='A whole number.') + + + class NonNegativeIntegerDatatype(BaseModel): + __root__: conint(ge=0) = Field(..., description='Non-negative integer.') + + + class BoundedIntegerDatatype(BaseModel): + __root__: conint(ge=0, le=100) = Field( + ..., description='Integer between 0 and 100.' + ) + + + class EmailDatatype(BaseModel): + __root__: EmailStr = Field(..., description='Email with format.') + + + class FormattedStringDatatype(BaseModel): + __root__: EmailStr = Field(..., description='A string with email format.') + + + class ObjectBase(BaseModel): + id: int | None = None + + + class ObjectWithAllOf(ObjectBase): + name: str | None = None + + + class MultiRefAllOf(BaseModel): + pass + + + class NoConstraintAllOf(BaseModel): + pass + + + class IncompatibleTypeAllOf(BaseModel): + pass + + + class ConstraintWithProperties(BaseModel): + extra: str | None = None + + + class ConstraintWithItems(BaseModel): + pass + + + class NumberIntegerCompatible(BaseModel): + __root__: conint(ge=0) = Field( + ..., description='Number and integer are compatible.' + ) + + + class RefWithSchemaKeywords(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$', min_length=5, max_length=100) = Field( + ..., description='Ref with additional schema keywords.' + ) + + + class ArrayDatatype(BaseModel): + __root__: list[str] + + + class RefToArrayAllOf(BaseModel): + pass + + + class ObjectNoPropsDatatype(BaseModel): + pass + + + class RefToObjectNoPropsAllOf(ObjectNoPropsDatatype): + pass + + + class PatternPropsDatatype(BaseModel): + __root__: dict[constr(regex=r'^S_'), str] + + + class RefToPatternPropsAllOf(BaseModel): + pass + + + class NestedAllOfDatatype(BaseModel): + pass + + + class RefToNestedAllOfAllOf(NestedAllOfDatatype): + pass + + + class ConstraintsOnlyDatatype(BaseModel): + __root__: Any = Field(..., description='Constraints only, no type.') + + + class RefToConstraintsOnlyAllOf(BaseModel): + __root__: Any = Field(..., description='Ref to constraints-only schema.') + + + class NoDescriptionAllOf(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$', min_length=5) = Field( + ..., description='A base string type.' + ) + + + class EmptyConstraintItemAllOf(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$', max_length=50) = Field( + ..., description='AllOf with empty constraint item.' + ) + + + class ConflictingFormatAllOf(BaseModel): + pass + + + class Model(BaseModel): + name: ConstrainedStringDatatype | None = None + count: NonNegativeIntegerDatatype | None = None + percentage: BoundedIntegerDatatype | None = None + email: EmailDatatype | None = None + obj: ObjectWithAllOf | None = None + multi: MultiRefAllOf | None = None + noconstraint: NoConstraintAllOf | None = None + incompatible: IncompatibleTypeAllOf | None = None + withprops: ConstraintWithProperties | None = None + withitems: ConstraintWithItems | None = None + numint: NumberIntegerCompatible | None = None + refwithkw: RefWithSchemaKeywords | None = None + refarr: RefToArrayAllOf | None = None + refobjnoprops: RefToObjectNoPropsAllOf | None = None + refpatternprops: RefToPatternPropsAllOf | None = None + refnestedallof: RefToNestedAllOfAllOf | None = None + refconstraintsonly: RefToConstraintsOnlyAllOf | None = None + nodescription: NoDescriptionAllOf | None = None + emptyconstraint: EmptyConstraintItemAllOf | None = None + conflictingformat: ConflictingFormatAllOf | None = None + ``` + + === "Without Option" + + ```python + # generated by datamodel-codegen: + # filename: allof_root_model_constraints.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel, EmailStr, Field, conint, constr + + + class StringDatatype(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$') = Field( + ..., description='A base string type.' + ) + + + class ConstrainedStringDatatype(BaseModel): + __root__: constr(regex=r'^[A-Z].*', min_length=1) = Field( + ..., description='A constrained string.' + ) + + + class IntegerDatatype(BaseModel): + __root__: int = Field(..., description='A whole number.') + + + class NonNegativeIntegerDatatype(BaseModel): + __root__: conint(ge=0) = Field(..., description='Non-negative integer.') + + + class BoundedIntegerDatatype(BaseModel): + __root__: conint(ge=0, le=100) = Field( + ..., description='Integer between 0 and 100.' + ) + + + class EmailDatatype(BaseModel): + __root__: EmailStr = Field(..., description='Email with format.') + + + class FormattedStringDatatype(BaseModel): + __root__: EmailStr = Field(..., description='A string with email format.') + + + class ObjectBase(BaseModel): + id: int | None = None + + + class ObjectWithAllOf(ObjectBase): + name: str | None = None + + + class MultiRefAllOf(BaseModel): + pass + + + class NoConstraintAllOf(BaseModel): + pass + + + class IncompatibleTypeAllOf(BaseModel): + pass + + + class ConstraintWithProperties(BaseModel): + extra: str | None = None + + + class ConstraintWithItems(BaseModel): + pass + + + class NumberIntegerCompatible(BaseModel): + __root__: conint(ge=0) = Field( + ..., description='Number and integer are compatible.' + ) + + + class RefWithSchemaKeywords(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$', min_length=5, max_length=100) = Field( + ..., description='Ref with additional schema keywords.' + ) + + + class ArrayDatatype(BaseModel): + __root__: list[str] + + + class RefToArrayAllOf(BaseModel): + pass + + + class ObjectNoPropsDatatype(BaseModel): + pass + + + class RefToObjectNoPropsAllOf(ObjectNoPropsDatatype): + pass + + + class PatternPropsDatatype(BaseModel): + __root__: dict[constr(regex=r'^S_'), str] + + + class RefToPatternPropsAllOf(BaseModel): + pass + + + class NestedAllOfDatatype(BaseModel): + pass + + + class RefToNestedAllOfAllOf(NestedAllOfDatatype): + pass + + + class ConstraintsOnlyDatatype(BaseModel): + __root__: Any = Field(..., description='Constraints only, no type.') + + + class RefToConstraintsOnlyAllOf(BaseModel): + __root__: Any = Field(..., description='Ref to constraints-only schema.') + + + class NoDescriptionAllOf(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$', min_length=5) = Field( + ..., description='A base string type.' + ) + + + class EmptyConstraintItemAllOf(BaseModel): + __root__: constr(regex=r'^\S(.*\S)?$', max_length=50) = Field( + ..., description='AllOf with empty constraint item.' + ) + + + class ConflictingFormatAllOf(BaseModel): + pass + + + class Model(BaseModel): + name: ConstrainedStringDatatype | None = None + count: NonNegativeIntegerDatatype | None = None + percentage: BoundedIntegerDatatype | None = None + email: EmailDatatype | None = None + obj: ObjectWithAllOf | None = None + multi: MultiRefAllOf | None = None + noconstraint: NoConstraintAllOf | None = None + incompatible: IncompatibleTypeAllOf | None = None + withprops: ConstraintWithProperties | None = None + withitems: ConstraintWithItems | None = None + numint: NumberIntegerCompatible | None = None + refwithkw: RefWithSchemaKeywords | None = None + refarr: RefToArrayAllOf | None = None + refobjnoprops: RefToObjectNoPropsAllOf | None = None + refpatternprops: RefToPatternPropsAllOf | None = None + refnestedallof: RefToNestedAllOfAllOf | None = None + refconstraintsonly: RefToConstraintsOnlyAllOf | None = None + nodescription: NoDescriptionAllOf | None = None + emptyconstraint: EmptyConstraintItemAllOf | None = None + conflictingformat: ConflictingFormatAllOf | None = None + ``` + +--- + +## `--disable-future-imports` {#disable-future-imports} + +Prevent automatic addition of __future__ imports in generated code. + +The --disable-future-imports option stops the generator from adding +'from __future__ import annotations' to the output. This is useful when +you need compatibility with tools or environments that don't support +postponed evaluation of annotations (PEP 563). + +**Python 3.13+ Deprecation Warning:** When using `from __future__ import annotations` +with older versions of Pydantic v1 (before 1.10.18), Python 3.13 may raise +deprecation warnings related to `typing._eval_type()`. To avoid these warnings: + +- Upgrade to Pydantic v1 >= 1.10.18 or Pydantic v2 (recommended) +- Use this `--disable-future-imports` flag as a workaround + +**See also:** [Python Version Compatibility](../python-version-compatibility.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --disable-future-imports --target-python-version 3.10 # (1)! + ``` + + 1. :material-arrow-left: `--disable-future-imports` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "DescriptionType", + "type": "object", + "properties": { + "metadata": { + "type": "array", + "items": { + "$ref": "#/definitions/Metadata" + } + } + }, + "definitions": { + "Metadata": { + "title": "Metadata", + "type": "object", + "properties": { + "title": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: keep_model_order_field_references.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from pydantic import BaseModel + + + class Metadata(BaseModel): + title: str | None = None + + + class DescriptionType(BaseModel): + metadata: list[Metadata] | None = None + ``` + +--- + +## `--enum-field-as-literal` {#enum-field-as-literal} + +Convert all enum fields to Literal types instead of Enum classes. + +The `--enum-field-as-literal all` flag converts all enum types to Literal +type annotations. This is useful when you want string literal types instead +of Enum classes for all enumerations. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --enum-field-as-literal all # (1)! + ``` + + 1. :material-arrow-left: `--enum-field-as-literal` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + + + 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] + boolean: Literal[True] + + + class Pets(BaseModel): + __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(BaseModel): + __root__: Literal['pet'] + + + class ArrayEnum(BaseModel): + __root__: list[Literal['cat'] | Literal['dog']] + + + class NestedVersionEnum(Enum): + RC1 = 'RC1' + RC1N = 'RC1N' + RC2 = 'RC2' + RC2N = 'RC2N' + RC3 = 'RC3' + RC4 = 'RC4' + + + class NestedVersion(BaseModel): + __root__: NestedVersionEnum | None = Field( + 'RC1', description='nullable enum', example='RC2' + ) + + + class NestedNullableEnum(BaseModel): + nested_version: NestedVersion | None = Field( + default_factory=lambda: NestedVersion.parse_obj('RC1'), + description='nullable enum', + example='RC2', + ) + + + class VersionEnum(Enum): + RC1 = 'RC1' + RC1N = 'RC1N' + RC2 = 'RC2' + RC2N = 'RC2N' + RC3 = 'RC3' + RC4 = 'RC4' + + + class Version(BaseModel): + __root__: VersionEnum | None = Field( + 'RC1', description='nullable enum', example='RC2' + ) + ``` + + === "JSON Schema" + + **Input Schema:** + + ```yaml + $schema: http://json-schema.org/draft-07/schema# + type: object + title: Config + properties: + mode: + title: Mode + type: string + oneOf: + - title: fast + const: fast + - title: slow + const: slow + modes: + type: array + items: + type: string + oneOf: + - const: a + - const: b + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: oneof_const_enum_nested.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal + + from pydantic import BaseModel, Field + + + class Config(BaseModel): + mode: Literal['fast', 'slow'] | None = Field(None, title='Mode') + modes: list[Literal['a', 'b']] | None = None + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + "Employee shift status" + enum EmployeeShiftStatus { + "not on shift" + NOT_ON_SHIFT + "on shift" + ON_SHIFT + } + + enum Color { + RED + GREEN + BLUE + } + + enum EnumWithOneField { + FIELD + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: enums.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal, TypeAlias + + from pydantic import BaseModel + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + class Color(BaseModel): + __root__: Literal['BLUE', 'GREEN', 'RED'] + + + class EmployeeShiftStatus(BaseModel): + """ + Employee shift status + """ + + __root__: Literal['NOT_ON_SHIFT', 'ON_SHIFT'] + + + class EnumWithOneField(BaseModel): + __root__: Literal['FIELD'] + ``` + + === "Without Option" + + ```python + # 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 import TypeAlias + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + class Color(Enum): + BLUE = 'BLUE' + GREEN = 'GREEN' + RED = 'RED' + + + class EmployeeShiftStatus(Enum): + """ + Employee shift status + """ + + NOT_ON_SHIFT = 'NOT_ON_SHIFT' + ON_SHIFT = 'ON_SHIFT' + + + class EnumWithOneField(Enum): + FIELD = 'FIELD' + ``` + +--- + +## `--enum-field-as-literal-map` {#enum-field-as-literal-map} + +Override enum/literal generation per-field via JSON mapping. + +The `--enum-field-as-literal-map` option allows per-field control over whether +to generate Literal types or Enum classes. Overrides `--enum-field-as-literal`. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --enum-field-as-literal-map "{"status": "literal"}" # (1)! + ``` + + 1. :material-arrow-left: `--enum-field-as-literal-map` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "EnumFieldAsLiteralMap", + "type": "object", + "properties": { + "status": { + "title": "Status", + "type": "string", + "enum": ["active", "inactive", "pending"] + }, + "priority": { + "title": "Priority", + "type": "string", + "enum": ["high", "medium", "low"] + }, + "category": { + "title": "Category", + "type": "string", + "enum": ["a", "b", "c"] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: enum_field_as_literal_map.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + from typing import Literal + + from pydantic import BaseModel, Field + + + class Priority(Enum): + high = 'high' + medium = 'medium' + low = 'low' + + + class Category(Enum): + a = 'a' + b = 'b' + c = 'c' + + + class EnumFieldAsLiteralMap(BaseModel): + status: Literal['active', 'inactive', 'pending'] | None = Field( + None, title='Status' + ) + priority: Priority | None = Field(None, title='Priority') + category: Category | None = Field(None, title='Category') + ``` + +--- + +## `--ignore-enum-constraints` {#ignore-enum-constraints} + +Ignore enum constraints and use base string type instead of Enum classes. + +The `--ignore-enum-constraints` flag ignores enum constraints and uses +the base type (str) instead of generating Enum classes. This is useful +when you need flexibility in the values a field can accept beyond the +defined enum members. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --ignore-enum-constraints # (1)! + ``` + + 1. :material-arrow-left: `--ignore-enum-constraints` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + "Employee shift status" + enum EmployeeShiftStatus { + "not on shift" + NOT_ON_SHIFT + "on shift" + ON_SHIFT + } + + enum Color { + RED + GREEN + BLUE + } + + enum EnumWithOneField { + FIELD + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: enums.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import TypeAlias + + from pydantic import BaseModel + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + class Color(BaseModel): + __root__: str + + + class EmployeeShiftStatus(BaseModel): + """ + Employee shift status + """ + + __root__: str + + + class EnumWithOneField(BaseModel): + __root__: str + ``` + + === "Without Option" + + ```python + # 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 import TypeAlias + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + class Color(Enum): + BLUE = 'BLUE' + GREEN = 'GREEN' + RED = 'RED' + + + class EmployeeShiftStatus(Enum): + """ + Employee shift status + """ + + NOT_ON_SHIFT = 'NOT_ON_SHIFT' + ON_SHIFT = 'ON_SHIFT' + + + class EnumWithOneField(Enum): + FIELD = 'FIELD' + ``` + +--- + +## `--no-use-specialized-enum` {#no-use-specialized-enum} + +Disable specialized Enum classes for Python 3.11+ code generation. + +The `--no-use-specialized-enum` flag prevents the generator from using +specialized Enum classes (StrEnum, IntEnum) when generating code for +Python 3.11+, falling back to standard Enum classes instead. + +**Related:** [`--target-python-version`](model-customization.md#target-python-version), [`--use-subclass-enum`](model-customization.md#use-subclass-enum) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --target-python-version 3.11 --no-use-specialized-enum # (1)! + ``` + + 1. :material-arrow-left: `--no-use-specialized-enum` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```json + { + "openapi": "3.0.2", + "components": { + "schemas": { + "ProcessingStatus": { + "title": "ProcessingStatus", + "enum": [ + "COMPLETED", + "PENDING", + "FAILED" + ], + "type": "string", + "description": "The processing status" + }, + "ProcessingTask": { + "title": "ProcessingTask", + "type": "object", + "properties": { + "processing_status": { + "title": "Status of the task", + "allOf": [ + { + "$ref": "#/components/schemas/ProcessingStatus" + } + ], + "default": "COMPLETED" + } + } + }, + } + }, + "info": { + "title": "", + "version": "" + }, + "paths": {} + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: subclass_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel, Field + + + class ProcessingStatus(Enum): + COMPLETED = 'COMPLETED' + PENDING = 'PENDING' + FAILED = 'FAILED' + + + class ProcessingTask(BaseModel): + processing_status: ProcessingStatus | None = Field( + 'COMPLETED', title='Status of the task' + ) + ``` + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "IntEnum": { + "type": "integer", + "enum": [ + 1, + 2, + 3 + ] + }, + "FloatEnum": { + "type": "number", + "enum": [ + 1.1, + 2.1, + 3.1 + ] + }, + "StrEnum": { + "type": "string", + "enum": [ + "1", + "2", + "3" + ] + }, + "NonTypedEnum": { + "enum": [ + "1", + "2", + "3" + ] + }, + "BooleanEnum": { + "type": "boolean", + "enum": [ + true, + false + ] + }, + "UnknownEnum": { + "type": "unknown", + "enum": [ + "a", + "b" + ] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: subclass_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel + + + class IntEnum(Enum): + integer_1 = 1 + integer_2 = 2 + integer_3 = 3 + + + class FloatEnum(Enum): + number_1_1 = 1.1 + number_2_1 = 2.1 + number_3_1 = 3.1 + + + class StrEnum(Enum): + field_1 = '1' + field_2 = '2' + field_3 = '3' + + + class NonTypedEnum(Enum): + field_1 = '1' + field_2 = '2' + field_3 = '3' + + + class BooleanEnum(Enum): + boolean_True = True + boolean_False = False + + + class UnknownEnum(Enum): + a = 'a' + b = 'b' + + + class Model(BaseModel): + IntEnum: IntEnum | None = None + FloatEnum: FloatEnum | None = None + StrEnum: StrEnum | None = None + NonTypedEnum: NonTypedEnum | None = None + BooleanEnum: BooleanEnum | None = None + UnknownEnum: UnknownEnum | None = None + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + "Employee shift status" + enum EmployeeShiftStatus { + "not on shift" + NOT_ON_SHIFT + "on shift" + ON_SHIFT + } + + enum Color { + RED + GREEN + BLUE + } + + enum EnumWithOneField { + FIELD + } + ``` + + **Output:** + + ```python + # 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 import TypeAlias + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + class Color(Enum): + BLUE = 'BLUE' + GREEN = 'GREEN' + RED = 'RED' + + + class EmployeeShiftStatus(Enum): + """ + Employee shift status + """ + + NOT_ON_SHIFT = 'NOT_ON_SHIFT' + ON_SHIFT = 'ON_SHIFT' + + + class EnumWithOneField(Enum): + FIELD = 'FIELD' + ``` + +--- + +## `--no-use-standard-collections` {#no-use-standard-collections} + +Use typing.Dict/List instead of built-in dict/list for container types. + +The `--no-use-standard-collections` flag generates typing module containers +(Dict, List) instead of built-in types. This is useful for older Python +versions or when explicit typing imports are preferred. + +**See also:** [Python Version Compatibility](../python-version-compatibility.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --no-use-standard-collections # (1)! + ``` + + 1. :material-arrow-left: `--no-use-standard-collections` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "test.json", + "description": "test", + "type": "object", + "required": [ + "test_id", + "test_ip", + "result", + "nested_object_result", + "nested_enum_result" + ], + "properties": { + "test_id": { + "type": "string", + "description": "test ID" + }, + "test_ip": { + "type": "string", + "description": "test IP" + }, + "result": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + }, + "nested_object_result": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "status":{ + "type": "integer" + } + }, + "required": ["status"] + } + }, + "nested_enum_result": { + "type": "object", + "additionalProperties": { + "enum": ["red", "green"] + } + }, + "all_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "one_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "oneOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "any_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "anyOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "all_of_with_unknown_object" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "description": "TODO" } + ] + } + }, + "objectRef": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + }, + "deepNestedObjectRef": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + } + } + } + }, + "definitions": { + "User": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: root_model_with_additional_properties.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + from typing import Dict + + from pydantic import BaseModel, Field + + + class NestedObjectResult(BaseModel): + status: int + + + class NestedEnumResult(Enum): + red = 'red' + green = 'green' + + + class OneOfResult(BaseModel): + description: str | None = None + + + class AnyOfResult(BaseModel): + description: str | None = None + + + class User(BaseModel): + name: str | None = None + + + class AllOfResult(User): + description: str | None = None + + + class Model(BaseModel): + test_id: str = Field(..., description='test ID') + test_ip: str = Field(..., description='test IP') + result: Dict[str, int] + nested_object_result: Dict[str, NestedObjectResult] + nested_enum_result: Dict[str, NestedEnumResult] + all_of_result: Dict[str, AllOfResult] | None = None + one_of_result: Dict[str, User | OneOfResult] | None = None + any_of_result: Dict[str, User | AnyOfResult] | None = None + all_of_with_unknown_object: Dict[str, User] | None = None + objectRef: Dict[str, User] | None = None + deepNestedObjectRef: Dict[str, Dict[str, Dict[str, User]]] | None = None + ``` + +--- + +## `--no-use-union-operator` {#no-use-union-operator} + +Use Union[X, Y] / Optional[X] instead of X | Y union operator. + +The `--no-use-union-operator` flag generates union types using typing.Union +and typing.Optional instead of the | operator (PEP 604). This is useful +for older Python versions or when explicit typing imports are preferred. + +**See also:** [Python Version Compatibility](../python-version-compatibility.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --no-use-union-operator # (1)! + ``` + + 1. :material-arrow-left: `--no-use-union-operator` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "test.json", + "description": "test", + "type": "object", + "required": [ + "test_id", + "test_ip", + "result", + "nested_object_result", + "nested_enum_result" + ], + "properties": { + "test_id": { + "type": "string", + "description": "test ID" + }, + "test_ip": { + "type": "string", + "description": "test IP" + }, + "result": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + }, + "nested_object_result": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "status":{ + "type": "integer" + } + }, + "required": ["status"] + } + }, + "nested_enum_result": { + "type": "object", + "additionalProperties": { + "enum": ["red", "green"] + } + }, + "all_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "one_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "oneOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "any_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "anyOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "all_of_with_unknown_object" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "description": "TODO" } + ] + } + }, + "objectRef": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + }, + "deepNestedObjectRef": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + } + } + } + }, + "definitions": { + "User": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: root_model_with_additional_properties.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + from typing import Optional, Union + + from pydantic import BaseModel, Field + + + class NestedObjectResult(BaseModel): + status: int + + + class NestedEnumResult(Enum): + red = 'red' + green = 'green' + + + class OneOfResult(BaseModel): + description: Optional[str] = None + + + class AnyOfResult(BaseModel): + description: Optional[str] = None + + + class User(BaseModel): + name: Optional[str] = None + + + class AllOfResult(User): + description: Optional[str] = None + + + class Model(BaseModel): + test_id: str = Field(..., description='test ID') + test_ip: str = Field(..., description='test IP') + result: dict[str, int] + nested_object_result: dict[str, NestedObjectResult] + nested_enum_result: dict[str, NestedEnumResult] + all_of_result: Optional[dict[str, AllOfResult]] = None + one_of_result: Optional[dict[str, Union[User, OneOfResult]]] = None + any_of_result: Optional[dict[str, Union[User, AnyOfResult]]] = None + all_of_with_unknown_object: Optional[dict[str, User]] = None + objectRef: Optional[dict[str, User]] = None + deepNestedObjectRef: Optional[dict[str, dict[str, dict[str, User]]]] = None + ``` + +--- + +## `--output-date-class` {#output-date-class} + +Specify date class type for date schema fields. + +The `--output-date-class` flag controls which date type to use for fields +with date format. Options include 'PastDate' for past dates only +or 'FutureDate' for future dates only. This is a Pydantic v2 only feature. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-date-class PastDate # (1)! + ``` + + 1. :material-arrow-left: `--output-date-class` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + components: + schemas: + Event: + type: object + required: + - eventDate + properties: + eventDate: + type: string + format: date + example: 2023-12-25 + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: date_class.yaml + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field, PastDate + + + class Event(BaseModel): + eventDate: PastDate = Field(..., examples=['2023-12-25']) + ``` + +--- + +## `--output-datetime-class` {#output-datetime-class} + +Specify datetime class type for date-time schema fields. + +The `--output-datetime-class` flag controls which datetime type to use for fields +with date-time format. Options include 'AwareDatetime' for timezone-aware datetimes +or 'datetime' for standard Python datetime objects. + +**See also:** [Type Mappings and Custom Types](../type-mappings.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-datetime-class AwareDatetime # (1)! + ``` + + 1. :material-arrow-left: `--output-datetime-class` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + components: + schemas: + InventoryItem: + required: + # - id + # - name + - releaseDate + type: object + properties: + # id: + # type: string + # format: uuid + # example: d290f1ee-6c54-4b01-90e6-d701748f0851 + # name: + # type: string + # example: Widget Adapter + releaseDate: + type: string + format: date-time + example: 2016-08-29T09:12:33.001Z + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: datetime.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AwareDatetime, BaseModel, Field + + + class InventoryItem(BaseModel): + releaseDate: AwareDatetime = Field(..., examples=['2016-08-29T09:12:33.001Z']) + ``` + +--- + +## `--strict-types` {#strict-types} + +Enable strict type validation for specified Python types. + +The --strict-types option enforces stricter type checking by preventing implicit +type coercion for the specified types (str, bytes, int, float, bool). This +generates StrictStr, StrictBytes, StrictInt, StrictFloat, and StrictBool types +in Pydantic models, ensuring values match exactly without automatic conversion. + +**See also:** [Type Mappings and Custom Types](../type-mappings.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --strict-types str bytes int float bool # (1)! + ``` + + 1. :material-arrow-left: `--strict-types` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "User", + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "ken" + }, + "age": { + "type": "integer" + }, + "salary": { + "type": "integer", + "minimum": 0 + }, + "debt" : { + "type": "integer", + "maximum": 0 + }, + "loan" : { + "type": "number", + "maximum": 0 + }, + "tel": { + "type": "string", + "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$" + }, + "height": { + "type": "number", + "minimum": 0 + }, + "weight": { + "type": "number", + "minimum": 0 + }, + "score": { + "type": "number", + "minimum": 1e-08 + }, + "active": { + "type": "boolean" + }, + "photo": { + "type": "string", + "format": "binary", + "minLength": 100 + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: strict_types.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import ( + BaseModel, + Field, + StrictBool, + StrictBytes, + StrictInt, + StrictStr, + confloat, + conint, + constr, + ) + + + class User(BaseModel): + name: StrictStr | None = Field(None, example='ken') + age: StrictInt | None = None + salary: conint(ge=0, strict=True) | None = None + debt: conint(le=0, strict=True) | None = None + loan: confloat(le=0.0, strict=True) | None = None + tel: constr(regex=r'^(\([0-9]{3}\))?[0-9]{3}-[0-9]{4}$', strict=True) | None = None + height: confloat(ge=0.0, strict=True) | None = None + weight: confloat(ge=0.0, strict=True) | None = None + score: confloat(ge=1e-08, strict=True) | None = None + active: StrictBool | None = None + photo: StrictBytes | None = None + ``` + +--- + +## `--type-mappings` {#type-mappings} + +Override default type mappings for schema formats. + +The `--type-mappings` flag configures the code generation behavior. + +**See also:** [Type Mappings and Custom Types](../type-mappings.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --type-mappings binary=string # (1)! + ``` + + 1. :material-arrow-left: `--type-mappings` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "BlobModel", + "type": "object", + "properties": { + "content": { + "type": "string", + "format": "binary", + "description": "Binary content that should be mapped to string" + }, + "data": { + "type": "string", + "format": "byte", + "description": "Base64 encoded data" + }, + "name": { + "type": "string", + "description": "Regular string field" + } + }, + "required": ["content", "data", "name"] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: type_mappings.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import Base64Str, BaseModel, Field + + + class BlobModel(BaseModel): + content: str = Field( + ..., description='Binary content that should be mapped to string' + ) + data: Base64Str = Field(..., description='Base64 encoded data') + name: str = Field(..., description='Regular string field') + ``` + +--- + +## `--type-overrides` {#type-overrides} + +Replace schema model types with custom Python types via JSON mapping. + +This option is useful for importing models from external libraries (like `geojson-pydantic`) +instead of generating them. + +**Override Formats:** + +| Format | Description | +|--------|-------------| +| `{"ModelName": "package.Type"}` | Model-level: Skip generating `ModelName` and import from `package` | +| `{"Model.field": "package.Type"}` | Scoped: Override only specific field in specific model | + +**Common Use Cases:** + +| Use Case | Example Override | +|----------|------------------| +| GeoJSON types | `{"Feature": "geojson_pydantic.Feature"}` | +| Custom datetime | `{"Timestamp": "pendulum.DateTime"}` | +| MongoDB ObjectId | `{"ObjectId": "bson.ObjectId"}` | +| Custom validators | `{"Email": "my_app.types.ValidatedEmail"}` | + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --type-overrides "{"CustomType": "my_app.types.CustomType"}" # (1)! + ``` + + 1. :material-arrow-left: `--type-overrides` - the option documented here + +!!! note "Model-level overrides skip generation" + When you specify a model-level override (without a dot in the key), the generator will + **skip generating that model entirely** and import it from the specified package instead. + + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "CustomType": {"type": "string"}, + "User": { + "type": "object", + "properties": { + "id": {"type": "integer"}, + "custom": {"$ref": "#/definitions/CustomType"} + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: type_overrides_test.json + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from typing import Any + + from my_app.types import CustomType + from pydantic import BaseModel + + + class Model(BaseModel): + __root__: Any + + + class User(BaseModel): + id: int | None = None + custom: CustomType | None = None + ``` + +--- + +## `--use-annotated` {#use-annotated} + +Use typing.Annotated for Field() with constraints. + +The `--use-annotated` flag generates Field definitions using typing.Annotated +syntax instead of default values. This also enables `--field-constraints`. + +**Related:** [`--field-constraints`](field-customization.md#field-constraints) + +**See also:** [Python Version Compatibility](../python-version-compatibility.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --use-annotated # (1)! + ``` + + 1. :material-arrow-left: `--use-annotated` - the option documented here + +??? example "Examples" + + === "OpenAPI" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + minimum: 0 + maximum: 100 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + minimum: 0 + maximum: 9223372036854775807 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + maxItems: 10 + minItems: 1 + uniqueItems: true + UID: + type: integer + minimum: 0 + Users: + type: array + items: + required: + - id + - name + - uid + properties: + id: + type: integer + format: int64 + minimum: 0 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + uid: + $ref: '#/components/schemas/UID' + phones: + type: array + items: + type: string + minLength: 3 + maxItems: 10 + fax: + type: array + items: + type: string + minLength: 3 + height: + type: + - integer + - number + minimum: 1 + maximum: 300 + weight: + type: + - number + - integer + minimum: 1.0 + maximum: 1000.0 + age: + type: integer + minimum: 0.0 + maximum: 200.0 + exclusiveMinimum: true + rating: + type: number + minimum: 0 + exclusiveMinimum: true + maximum: 5 + + Id: + type: string + Rules: + type: array + items: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: To be used as a dataset parameter value + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + minLength: 1 + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: api_constrained.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: Annotated[int, Field(ge=0, le=9223372036854775807)] + name: Annotated[str, Field(max_length=256)] + tag: Annotated[str | None, Field(max_length=64)] = None + + + class Pets(BaseModel): + __root__: Annotated[list[Pet], Field(max_items=10, min_items=1, unique_items=True)] + + + class UID(BaseModel): + __root__: Annotated[int, Field(ge=0)] + + + class Phone(BaseModel): + __root__: Annotated[str, Field(min_length=3)] + + + class FaxItem(BaseModel): + __root__: Annotated[str, Field(min_length=3)] + + + class User(BaseModel): + id: Annotated[int, Field(ge=0)] + name: Annotated[str, Field(max_length=256)] + tag: Annotated[str | None, Field(max_length=64)] = None + uid: UID + phones: Annotated[list[Phone] | None, Field(max_items=10)] = None + fax: list[FaxItem] | None = None + height: Annotated[int | float | None, Field(ge=1.0, le=300.0)] = None + weight: Annotated[float | int | None, Field(ge=1.0, le=1000.0)] = None + age: Annotated[int | None, Field(gt=0, le=200)] = None + rating: Annotated[float | None, Field(gt=0.0, le=5.0)] = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: Annotated[ + str | None, Field(description='To be used as a dataset parameter value') + ] = None + apiVersionNumber: Annotated[ + str | None, Field(description='To be used as a version parameter value') + ] = None + apiUrl: Annotated[ + AnyUrl | None, Field(description="The URL describing the dataset's fields") + ] = None + apiDocumentationUrl: Annotated[ + AnyUrl | None, Field(description='A URL to the API console for each API') + ] = None + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + type A { + field: String! + optionalField: String + listField: [String!]! + listOptionalField: [String]! + optionalListField: [String!] + optionalListOptionalField: [String] + listListField:[[String!]!]! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: annotated.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated, 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__: Annotated[Literal['A'] | None, Field(alias='__typename')] = 'A' + ``` + +--- + +## `--use-decimal-for-multiple-of` {#use-decimal-for-multiple-of} + +Generate Decimal types for fields with multipleOf constraint. + +The `--use-decimal-for-multiple-of` flag generates `condecimal` or `Decimal` +types for numeric fields that have a `multipleOf` constraint. This ensures +precise decimal arithmetic when validating values against the constraint. + +**See also:** [Type Mappings and Custom Types](../type-mappings.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-decimal-for-multiple-of # (1)! + ``` + + 1. :material-arrow-left: `--use-decimal-for-multiple-of` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "type": "object", + "properties": { + "price": { + "type": "number", + "multipleOf": 0.01, + "minimum": 0, + "maximum": 99999.99 + }, + "quantity": { + "type": "number", + "multipleOf": 0.1 + }, + "rate": { + "type": "number", + "multipleOf": 0.001, + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + }, + "simple_float": { + "type": "number", + "minimum": 0, + "maximum": 100 + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: use_decimal_for_multiple_of.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, condecimal, confloat + + + class Model(BaseModel): + price: condecimal(ge=0, le=99999.99, multiple_of=0.01) | None = None + quantity: condecimal(multiple_of=0.1) | None = None + rate: condecimal(multiple_of=0.001, lt=1.0, gt=0.0) | None = None + simple_float: confloat(ge=0.0, le=100.0) | None = None + ``` + +--- + +## `--use-generic-container-types` {#use-generic-container-types} + +Use generic container types (Sequence, Mapping) for type hinting. + +The `--use-generic-container-types` flag generates abstract container types +(Sequence, Mapping, FrozenSet) instead of concrete types (list, dict, set). +If `--use-standard-collections` is set, imports from `collections.abc`; +otherwise imports from `typing`. + +**Related:** [`--no-use-standard-collections`](typing-customization.md#no-use-standard-collections) + +**See also:** [Python Version Compatibility](../python-version-compatibility.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-generic-container-types # (1)! + ``` + + 1. :material-arrow-left: `--use-generic-container-types` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "test.json", + "description": "test", + "type": "object", + "required": [ + "test_id", + "test_ip", + "result", + "nested_object_result", + "nested_enum_result" + ], + "properties": { + "test_id": { + "type": "string", + "description": "test ID" + }, + "test_ip": { + "type": "string", + "description": "test IP" + }, + "result": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + }, + "nested_object_result": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "status":{ + "type": "integer" + } + }, + "required": ["status"] + } + }, + "nested_enum_result": { + "type": "object", + "additionalProperties": { + "enum": ["red", "green"] + } + }, + "all_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "one_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "oneOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "any_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "anyOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "all_of_with_unknown_object" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "description": "TODO" } + ] + } + }, + "objectRef": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + }, + "deepNestedObjectRef": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + } + } + } + }, + "definitions": { + "User": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: root_model_with_additional_properties.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from collections.abc import Mapping + from enum import Enum + + from pydantic import BaseModel, Field + + + class NestedObjectResult(BaseModel): + status: int + + + class NestedEnumResult(Enum): + red = 'red' + green = 'green' + + + class OneOfResult(BaseModel): + description: str | None = None + + + class AnyOfResult(BaseModel): + description: str | None = None + + + class User(BaseModel): + name: str | None = None + + + class AllOfResult(User): + description: str | None = None + + + class Model(BaseModel): + test_id: str = Field(..., description='test ID') + test_ip: str = Field(..., description='test IP') + result: Mapping[str, int] + nested_object_result: Mapping[str, NestedObjectResult] + nested_enum_result: Mapping[str, NestedEnumResult] + all_of_result: Mapping[str, AllOfResult] | None = None + one_of_result: Mapping[str, User | OneOfResult] | None = None + any_of_result: Mapping[str, User | AnyOfResult] | None = None + all_of_with_unknown_object: Mapping[str, User] | None = None + objectRef: Mapping[str, User] | None = None + deepNestedObjectRef: Mapping[str, Mapping[str, Mapping[str, User]]] | None = None + ``` + +--- + +## `--use-non-positive-negative-number-constrained-types` {#use-non-positive-negative-number-constrained-types} + +Use NonPositive/NonNegative types for number constraints. + +The `--use-non-positive-negative-number-constrained-types` flag generates +Pydantic's NonPositiveInt, NonNegativeInt, NonPositiveFloat, and NonNegativeFloat +types for fields with minimum: 0 or maximum: 0 constraints, instead of using +conint/confloat with ge/le parameters. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-non-positive-negative-number-constrained-types # (1)! + ``` + + 1. :material-arrow-left: `--use-non-positive-negative-number-constrained-types` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NumberConstraints", + "type": "object", + "properties": { + "non_negative_count": { + "type": "integer", + "minimum": 0, + "description": "A count that cannot be negative" + }, + "non_positive_balance": { + "type": "integer", + "maximum": 0, + "description": "A balance that cannot be positive" + }, + "non_negative_amount": { + "type": "number", + "minimum": 0, + "description": "An amount that cannot be negative" + }, + "non_positive_score": { + "type": "number", + "maximum": 0, + "description": "A score that cannot be positive" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: use_non_positive_negative.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import ( + BaseModel, + Field, + NonNegativeFloat, + NonNegativeInt, + NonPositiveFloat, + NonPositiveInt, + ) + + + class NumberConstraints(BaseModel): + non_negative_count: NonNegativeInt | None = Field( + None, description='A count that cannot be negative' + ) + non_positive_balance: NonPositiveInt | None = Field( + None, description='A balance that cannot be positive' + ) + non_negative_amount: NonNegativeFloat | None = Field( + None, description='An amount that cannot be negative' + ) + non_positive_score: NonPositiveFloat | None = Field( + None, description='A score that cannot be positive' + ) + ``` + +--- + +## `--use-pendulum` {#use-pendulum} + +Use pendulum types for date/time fields instead of datetime module. + +The `--use-pendulum` flag generates pendulum library types (DateTime, Date, +Time, Duration) instead of standard datetime types. This is useful when +working with the pendulum library for enhanced timezone and date handling. + +**See also:** [Type Mappings and Custom Types](../type-mappings.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-pendulum # (1)! + ``` + + 1. :material-arrow-left: `--use-pendulum` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Event", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "event_date": { + "type": "string", + "format": "date" + }, + "duration": { + "type": "string", + "format": "duration" + } + }, + "required": ["name", "created_at"] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: use_pendulum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pendulum import Date, DateTime, Duration + from pydantic import BaseModel + + + class Event(BaseModel): + name: str + created_at: DateTime + event_date: Date | None = None + duration: Duration | None = None + ``` + +--- + +## `--use-root-model-type-alias` {#use-root-model-type-alias} + +Generate RootModel as type alias format for better mypy support. + +When enabled, root models with simple types are generated as type aliases +instead of class definitions, improving mypy type inference. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-root-model-type-alias --output-model-type pydantic_v2.BaseModel # (1)! + ``` + + 1. :material-arrow-left: `--use-root-model-type-alias` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "Pet": { + "type": "object", + "properties": { + "name": {"type": "string"} + } + }, + "Pets": { + "oneOf": [ + {"$ref": "#/definitions/Pet"}, + {"type": "array", "items": {"$ref": "#/definitions/Pet"}} + ] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: root_model_type_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel, RootModel + + Model = RootModel[Any] + + + class Pet(BaseModel): + name: str | None = None + + + Pets = RootModel[Pet | list[Pet]] + ``` + +--- + +## `--use-specialized-enum` {#use-specialized-enum} + +Generate StrEnum/IntEnum for string/integer enums (Python 3.11+). + +The `--use-specialized-enum` flag generates specialized enum types: +- `StrEnum` for string enums +- `IntEnum` for integer enums + +This is the default behavior for Python 3.11+ targets. + +**Related:** [`--no-use-specialized-enum`](typing-customization.md#no-use-specialized-enum), [`--use-subclass-enum`](model-customization.md#use-subclass-enum) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --target-python-version 3.11 --use-specialized-enum # (1)! + ``` + + 1. :material-arrow-left: `--use-specialized-enum` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "IntEnum": { + "type": "integer", + "enum": [ + 1, + 2, + 3 + ] + }, + "FloatEnum": { + "type": "number", + "enum": [ + 1.1, + 2.1, + 3.1 + ] + }, + "StrEnum": { + "type": "string", + "enum": [ + "1", + "2", + "3" + ] + }, + "NonTypedEnum": { + "enum": [ + "1", + "2", + "3" + ] + }, + "BooleanEnum": { + "type": "boolean", + "enum": [ + true, + false + ] + }, + "UnknownEnum": { + "type": "unknown", + "enum": [ + "a", + "b" + ] + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: subclass_enum.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum, IntEnum, StrEnum + + from pydantic import BaseModel + + + class IntEnumModel(IntEnum): + integer_1 = 1 + integer_2 = 2 + integer_3 = 3 + + + class FloatEnum(Enum): + number_1_1 = 1.1 + number_2_1 = 2.1 + number_3_1 = 3.1 + + + class StrEnumModel(StrEnum): + field_1 = '1' + field_2 = '2' + field_3 = '3' + + + class NonTypedEnum(Enum): + field_1 = '1' + field_2 = '2' + field_3 = '3' + + + class BooleanEnum(Enum): + boolean_True = True + boolean_False = False + + + class UnknownEnum(Enum): + a = 'a' + b = 'b' + + + class Model(BaseModel): + IntEnum: IntEnumModel | None = None + FloatEnum: FloatEnum | None = None + StrEnum: StrEnumModel | None = None + NonTypedEnum: NonTypedEnum | None = None + BooleanEnum: BooleanEnum | None = None + UnknownEnum: UnknownEnum | None = None + ``` + +--- + +## `--use-standard-collections` {#use-standard-collections} + +Use built-in dict/list instead of typing.Dict/List. + +The `--use-standard-collections` flag generates built-in container types +(dict, list) instead of typing module equivalents. This produces cleaner +code for Python 3.10+ where built-in types support subscripting. + +**Related:** [`--use-generic-container-types`](typing-customization.md#use-generic-container-types) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-standard-collections # (1)! + ``` + + 1. :material-arrow-left: `--use-standard-collections` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "test.json", + "description": "test", + "type": "object", + "required": [ + "test_id", + "test_ip", + "result", + "nested_object_result", + "nested_enum_result" + ], + "properties": { + "test_id": { + "type": "string", + "description": "test ID" + }, + "test_ip": { + "type": "string", + "description": "test IP" + }, + "result": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + }, + "nested_object_result": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "status":{ + "type": "integer" + } + }, + "required": ["status"] + } + }, + "nested_enum_result": { + "type": "object", + "additionalProperties": { + "enum": ["red", "green"] + } + }, + "all_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "one_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "oneOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "any_of_result" :{ + "type" : "object", + "additionalProperties" : + { + "anyOf" : [ + { "$ref" : "#/definitions/User" }, + { "type" : "object", + "properties": { + "description": {"type" : "string" } + } + } + ] + } + }, + "all_of_with_unknown_object" :{ + "type" : "object", + "additionalProperties" : + { + "allOf" : [ + { "$ref" : "#/definitions/User" }, + { "description": "TODO" } + ] + } + }, + "objectRef": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + }, + "deepNestedObjectRef": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/User" + } + } + } + } + }, + "definitions": { + "User": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: root_model_with_additional_properties.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from enum import Enum + + from pydantic import BaseModel, Field + + + class NestedObjectResult(BaseModel): + status: int + + + class NestedEnumResult(Enum): + red = 'red' + green = 'green' + + + class OneOfResult(BaseModel): + description: str | None = None + + + class AnyOfResult(BaseModel): + description: str | None = None + + + class User(BaseModel): + name: str | None = None + + + class AllOfResult(User): + description: str | None = None + + + class Model(BaseModel): + test_id: str = Field(..., description='test ID') + test_ip: str = Field(..., description='test IP') + result: dict[str, int] + nested_object_result: dict[str, NestedObjectResult] + nested_enum_result: dict[str, NestedEnumResult] + all_of_result: dict[str, AllOfResult] | None = None + one_of_result: dict[str, User | OneOfResult] | None = None + any_of_result: dict[str, User | AnyOfResult] | None = None + all_of_with_unknown_object: dict[str, User] | None = None + objectRef: dict[str, User] | None = None + deepNestedObjectRef: dict[str, dict[str, dict[str, User]]] | None = None + ``` + +--- + +## `--use-standard-primitive-types` {#use-standard-primitive-types} + +Use Python standard library types for string formats instead of str. + +The `--use-standard-primitive-types` flag configures the code generation to use +Python standard library types (UUID, IPv4Address, IPv6Address, Path) for corresponding +string formats instead of plain str. This affects dataclass, msgspec, and TypedDict +output types. Pydantic already uses these types by default. + +**Related:** [`--output-datetime-class`](typing-customization.md#output-datetime-class), [`--output-model-type`](model-customization.md#output-model-type) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass --use-standard-primitive-types # (1)! + ``` + + 1. :material-arrow-left: `--use-standard-primitive-types` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "ip_address": { + "type": "string", + "format": "ipv4" + }, + "config_path": { + "type": "string", + "format": "path" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: use_standard_primitive_types.json + + from __future__ import annotations + + from dataclasses import dataclass + from ipaddress import IPv4Address + from pathlib import Path + from uuid import UUID + + + @dataclass + class Model: + id: UUID | None = None + ip_address: IPv4Address | None = None + config_path: Path | None = None + ``` + +--- + +## `--use-tuple-for-fixed-items` {#use-tuple-for-fixed-items} + +Generate tuple types for arrays with items array syntax. + +When `--use-tuple-for-fixed-items` is enabled and an array has `items` as an array +with `minItems == maxItems == len(items)`, generate a tuple type instead of a list. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-tuple-for-fixed-items # (1)! + ``` + + 1. :material-arrow-left: `--use-tuple-for-fixed-items` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "https://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "point": { + "type": "array", + "items": [{"type": "number"}, {"type": "number"}], + "minItems": 2, + "maxItems": 2 + } + }, + "required": ["point"] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: items_array_tuple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Model(BaseModel): + point: tuple[float, float] + ``` + +--- + +## `--use-type-alias` {#use-type-alias} + +Use TypeAlias instead of root models for type definitions (experimental). + +The `--use-type-alias` flag generates TypeAlias declarations instead of +root model classes for certain type definitions. For Python 3.10-3.11, it +generates TypeAliasType, and for Python 3.12+, it uses the 'type' statement +syntax. This feature is experimental. + +**Related:** [`--target-python-version`](model-customization.md#target-python-version) + +**See also:** [Model Reuse and Deduplication](../model-reuse.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-type-alias # (1)! + ``` + + 1. :material-arrow-left: `--use-type-alias` - the option documented here + +??? example "Examples" + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "SimpleString": { + "type": "string" + }, + "UnionType": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"} + ] + }, + "ArrayType": { + "type": "array", + "items": {"type": "string"} + }, + "AnnotatedType": { + "title": "MyAnnotatedType", + "description": "An annotated union type", + "anyOf": [ + {"type": "string"}, + {"type": "boolean"} + ] + }, + "ModelWithTypeAliasField": { + "type": "object", + "properties": { + "simple_field": {"$ref": "#/definitions/SimpleString"}, + "union_field": {"$ref": "#/definitions/UnionType"}, + "array_field": {"$ref": "#/definitions/ArrayType"}, + "annotated_field": {"$ref": "#/definitions/AnnotatedType"} + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: type_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated, Any, TypeAlias + + from pydantic import BaseModel, Field + + Model: TypeAlias = Any + + + SimpleString: TypeAlias = str + + + UnionType: TypeAlias = str | int + + + ArrayType: TypeAlias = list[str] + + + AnnotatedType: TypeAlias = Annotated[ + str | bool, + Field(..., description='An annotated union type', title='MyAnnotatedType'), + ] + + + class ModelWithTypeAliasField(BaseModel): + simple_field: SimpleString | None = None + union_field: UnionType | None = None + array_field: ArrayType | None = None + annotated_field: AnnotatedType | None = None + ``` + + === "GraphQL" + + **Input Schema:** + + ```graphql + scalar SimpleString + + type Person { + name: String! + age: Int! + } + + type Pet { + name: String! + type: String! + } + + union UnionType = Person | Pet + + type ModelWithTypeAliasField { + simple_field: SimpleString + union_field: UnionType + string_field: String + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: type_alias.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal, TypeAlias, Union + + from pydantic import BaseModel, Field + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + 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. + """ + + + SimpleString: TypeAlias = str + + + 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. + """ + + + class Person(BaseModel): + age: Int + name: String + typename__: Literal['Person'] | None = Field('Person', alias='__typename') + + + class Pet(BaseModel): + name: String + type: String + typename__: Literal['Pet'] | None = Field('Pet', alias='__typename') + + + UnionType: TypeAlias = Union[ + 'Person', + 'Pet', + ] + + + class ModelWithTypeAliasField(BaseModel): + simple_field: SimpleString | None = None + string_field: String | None = None + union_field: UnionType | None = None + typename__: Literal['ModelWithTypeAliasField'] | None = Field( + 'ModelWithTypeAliasField', alias='__typename' + ) + ``` + +--- + +## `--use-union-operator` {#use-union-operator} + +Use | operator for Union types (PEP 604). + +The `--use-union-operator` flag generates union types using the | operator +(e.g., `str | None`) instead of `Union[str, None]` or `Optional[str]`. +This is the default behavior. + +**Related:** [`--no-use-union-operator`](typing-customization.md#no-use-union-operator) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --use-annotated --use-union-operator # (1)! + ``` + + 1. :material-arrow-left: `--use-union-operator` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + type A { + field: String! + optionalField: String + listField: [String!]! + listOptionalField: [String]! + optionalListField: [String!] + optionalListOptionalField: [String] + listListField:[[String!]!]! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: annotated.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Annotated, 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__: Annotated[Literal['A'] | None, Field(alias='__typename')] = 'A' + ``` + +--- + +## `--use-unique-items-as-set` {#use-unique-items-as-set} + +Generate set types for arrays with uniqueItems constraint. + +The `--use-unique-items-as-set` flag generates Python set types instead of +list types for JSON Schema arrays that have the uniqueItems constraint set +to true, enforcing uniqueness at the type level. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-unique-items-as-set --field-constraints # (1)! + ``` + + 1. :material-arrow-left: `--use-unique-items-as-set` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + minimum: 0 + maximum: 100 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + minimum: 0 + maximum: 9223372036854775807 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + maxItems: 10 + minItems: 1 + uniqueItems: true + UID: + type: integer + minimum: 0 + Users: + type: array + items: + required: + - id + - name + - uid + properties: + id: + type: integer + format: int64 + minimum: 0 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + uid: + $ref: '#/components/schemas/UID' + phones: + type: array + items: + type: string + minLength: 3 + maxItems: 10 + fax: + type: array + items: + type: string + minLength: 3 + height: + type: + - integer + - number + minimum: 1 + maximum: 300 + weight: + type: + - number + - integer + minimum: 1.0 + maximum: 1000.0 + age: + type: integer + minimum: 0.0 + maximum: 200.0 + exclusiveMinimum: true + rating: + type: number + minimum: 0 + exclusiveMinimum: true + maximum: 5 + + Id: + type: string + Rules: + type: array + items: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: To be used as a dataset parameter value + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + minLength: 1 + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: api_constrained.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int = Field(..., ge=0, le=9223372036854775807) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + + + class Pets(BaseModel): + __root__: set[Pet] = Field(..., max_items=10, min_items=1, unique_items=True) + + + class UID(BaseModel): + __root__: int = Field(..., ge=0) + + + class Phone(BaseModel): + __root__: str = Field(..., min_length=3) + + + class FaxItem(BaseModel): + __root__: str = Field(..., min_length=3) + + + class User(BaseModel): + id: int = Field(..., ge=0) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + uid: UID + phones: list[Phone] | None = Field(None, max_items=10) + fax: list[FaxItem] | None = None + height: int | float | None = Field(None, ge=1.0, le=300.0) + weight: float | int | None = Field(None, ge=1.0, le=1000.0) + age: int | None = Field(None, gt=0, le=200) + rating: float | None = Field(None, gt=0.0, le=5.0) + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +--- + +# Template Customization + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/template-customization/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--additional-imports`](#additional-imports) | Add custom imports to generated output files. | +| [`--class-decorators`](#class-decorators) | Add custom decorators to generated model classes. | +| [`--custom-file-header`](#custom-file-header) | Add custom header text to the generated file. | +| [`--custom-file-header-path`](#custom-file-header-path) | Add custom header content from file to generated code. | +| [`--custom-formatters`](#custom-formatters) | Apply custom Python code formatters to generated output. | +| [`--custom-formatters-kwargs`](#custom-formatters-kwargs) | Pass custom arguments to custom formatters via JSON file. | +| [`--custom-template-dir`](#custom-template-dir) | Use custom Jinja2 templates for model generation. | +| [`--disable-appending-item-suffix`](#disable-appending-item-suffix) | Disable appending 'Item' suffix to array item types. | +| [`--disable-timestamp`](#disable-timestamp) | Disable timestamp in generated file header for reproducible ... | +| [`--enable-command-header`](#enable-command-header) | Include command-line options in file header for reproducibil... | +| [`--enable-version-header`](#enable-version-header) | Include tool version information in file header. | +| [`--extra-template-data`](#extra-template-data) | Pass custom template variables from JSON file for code gener... | +| [`--formatters`](#formatters) | Specify code formatters to apply to generated output. | +| [`--no-treat-dot-as-module`](#no-treat-dot-as-module) | Keep dots in schema names as underscores for flat output. | +| [`--treat-dot-as-module`](#treat-dot-as-module) | Treat dots in schema names as module separators. | +| [`--use-double-quotes`](#use-double-quotes) | Use double quotes for string literals in generated code. | +| [`--use-exact-imports`](#use-exact-imports) | Import exact types instead of modules. | +| [`--validators`](#validators) | Add custom field validators to generated Pydantic v2 models.... | +| [`--wrap-string-literal`](#wrap-string-literal) | Wrap long string literals across multiple lines. | + +--- + +## `--additional-imports` {#additional-imports} + +Add custom imports to generated output files. + +The `--additional-imports` flag allows you to specify custom imports as a +comma-delimited list that will be added to the generated output file. This +is useful when using custom types defined in external modules (e.g., +"datetime.datetime,datetime.date,mymodule.myclass.MyCustomPythonClass"). + +**See also:** [Custom Class Decorators](../class-decorators.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --additional-imports datetime.datetime,datetime.date,mymodule.myclass.MyCustomPythonClass # (1)! + ``` + + 1. :material-arrow-left: `--additional-imports` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + scalar Date + + "DateTime (ISO8601, example: 2020-01-01T10:11:12+00:00)" + scalar DateTime + + scalar MyCustomClass + + type A { + a: Date! + b: DateTime! + c: MyCustomClass! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: additional-imports.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from datetime import date, datetime + from typing import Literal, TypeAlias + + from mymodule.myclass import MyCustomPythonClass + from pydantic import BaseModel, Field + + Boolean: TypeAlias = bool + """ + The `Boolean` scalar type represents `true` or `false`. + """ + + + Date: TypeAlias = date + + + DateTime: TypeAlias = datetime + """ + DateTime (ISO8601, example: 2020-01-01T10:11:12+00:00) + """ + + + MyCustomClass: TypeAlias = MyCustomPythonClass + + + 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. + """ + + + class A(BaseModel): + a: Date + b: DateTime + c: MyCustomClass + typename__: Literal['A'] | None = Field('A', alias='__typename') + ``` + +--- + +## `--class-decorators` {#class-decorators} + +Add custom decorators to generated model classes. + +The `--class-decorators` option adds custom decorators to all generated model classes. +This is useful for integrating with serialization libraries like `dataclasses_json`. + +Use with `--additional-imports` to add the required imports for the decorators. +The `@` prefix is optional and will be added automatically if missing. + +**Related:** [`--additional-imports`](template-customization.md#additional-imports), [`--output-model-type`](model-customization.md#output-model-type) + +**See also:** [Custom Class Decorators](../class-decorators.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass --class-decorators @dataclass_json --additional-imports dataclasses_json.dataclass_json # (1)! + ``` + + 1. :material-arrow-left: `--class-decorators` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$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:** + + ```python + # generated by datamodel-codegen: + # filename: simple_frozen_test.json + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from dataclasses import dataclass + + from dataclasses_json import dataclass_json + + + @dataclass_json + @dataclass + class User: + name: str + age: int + email: str | None = None + ``` + +--- + +## `--custom-file-header` {#custom-file-header} + +Add custom header text to the generated file. + +The `--custom-file-header` flag replaces the default "generated by datamodel-codegen" +header with custom text. This is useful for adding copyright notices, license +headers, or other metadata to generated files. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --custom-file-header "# Copyright 2024 MyCompany" # (1)! + ``` + + 1. :material-arrow-left: `--custom-file-header` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "first-name": { + "type": "string" + }, + "last-name": { + "type": "string" + }, + "email_address": { + "type": "string" + } + }, + "required": ["first-name", "last-name"] + } + ``` + + **Output:** + + === "With Option" + + ```python + # Copyright 2024 MyCompany + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Person(BaseModel): + first_name: str = Field(..., alias='first-name') + last_name: str = Field(..., alias='last-name') + email_address: str | None = None + ``` + + === "Without Option" + + ```python + # generated by datamodel-codegen: + # filename: no_alias.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Person(BaseModel): + first_name: str = Field(..., alias='first-name') + last_name: str = Field(..., alias='last-name') + email_address: str | None = None + ``` + +--- + +## `--custom-file-header-path` {#custom-file-header-path} + +Add custom header content from file to generated code. + +The `--custom-file-header-path` flag allows you to specify a file containing +custom header content (like copyright notices, linting directives, or module docstrings) +to be inserted at the top of generated Python files. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --custom-file-header-path custom_file_header.txt # (1)! + ``` + + 1. :material-arrow-left: `--custom-file-header-path` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # multiline custom ; + # header ; + # file ; + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--custom-formatters` {#custom-formatters} + +Apply custom Python code formatters to generated output. + +The `--custom-formatters` flag allows you to specify custom Python functions +that will be applied to format the generated code. The formatter is specified +as a module path (e.g., "mymodule.formatter_function"). This is useful for +adding custom comments, modifying code structure, or applying project-specific +formatting rules beyond what black/isort provide. + +**See also:** [Custom Code Formatters](../custom-formatters.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --custom-formatters tests.data.python.custom_formatters.add_comment # (1)! + ``` + + 1. :material-arrow-left: `--custom-formatters` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + scalar Long + + type A { + id: ID! + duration: Long! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: custom-scalar-types.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + # a comment + from __future__ import annotations + + from typing import Literal, TypeAlias + + from pydantic import BaseModel, Field + + 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. + """ + + + Long: TypeAlias = str + + + 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. + """ + + + class A(BaseModel): + duration: Long + id: ID + typename__: Literal['A'] | None = Field('A', alias='__typename') + ``` + +--- + +## `--custom-formatters-kwargs` {#custom-formatters-kwargs} + +Pass custom arguments to custom formatters via JSON file. + +The `--custom-formatters-kwargs` flag accepts a path to a JSON file containing +custom configuration for custom formatters (used with --custom-formatters). +The file should contain a JSON object mapping formatter names to their kwargs. + +Note: This option is primarily used with --custom-formatters to pass +configuration to user-defined formatter modules. + +**See also:** [Custom Code Formatters](../custom-formatters.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --custom-formatters-kwargs formatter_kwargs.json # (1)! + ``` + + 1. :material-arrow-left: `--custom-formatters-kwargs` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet_simple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--custom-template-dir` {#custom-template-dir} + +Use custom Jinja2 templates for model generation. + +The `--custom-template-dir` option allows you to specify a directory containing custom Jinja2 templates +to override the default templates used for generating data models. This enables full customization of +the generated code structure and formatting. Use with `--extra-template-data` to pass additional data +to the templates. + +**See also:** [Custom Templates](../custom_template.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --custom-template-dir templates --extra-template-data openapi/extra_data.json # (1)! + ``` + + 1. :material-arrow-left: `--custom-template-dir` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): # 1 2, 1 2, this is just a pet + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = None + apiVersionNumber: str | None = None + apiUrl: AnyUrl | None = None + apiDocumentationUrl: AnyUrl | None = None + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--disable-appending-item-suffix` {#disable-appending-item-suffix} + +Disable appending 'Item' suffix to array item types. + +The `--disable-appending-item-suffix` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --disable-appending-item-suffix --field-constraints # (1)! + ``` + + 1. :material-arrow-left: `--disable-appending-item-suffix` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + minimum: 0 + maximum: 100 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + x-amazon-apigateway-integration: + uri: + Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations + passthroughBehavior: when_no_templates + httpMethod: POST + type: aws_proxy + components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + minimum: 0 + maximum: 9223372036854775807 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + maxItems: 10 + minItems: 1 + uniqueItems: true + UID: + type: integer + minimum: 0 + Users: + type: array + items: + required: + - id + - name + - uid + properties: + id: + type: integer + format: int64 + minimum: 0 + name: + type: string + maxLength: 256 + tag: + type: string + maxLength: 64 + uid: + $ref: '#/components/schemas/UID' + phones: + type: array + items: + type: string + minLength: 3 + maxItems: 10 + fax: + type: array + items: + type: string + minLength: 3 + height: + type: + - integer + - number + minimum: 1 + maximum: 300 + weight: + type: + - number + - integer + minimum: 1.0 + maximum: 1000.0 + age: + type: integer + minimum: 0.0 + maximum: 200.0 + exclusiveMinimum: true + rating: + type: number + minimum: 0 + exclusiveMinimum: true + maximum: 5 + + Id: + type: string + Rules: + type: array + items: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: To be used as a dataset parameter value + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uri + minLength: 1 + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uri + description: A URL to the API console for each API + Event: + type: object + properties: + name: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/Event' + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: api_constrained.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int = Field(..., ge=0, le=9223372036854775807) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + + + class Pets(BaseModel): + __root__: list[Pet] = Field(..., max_items=10, min_items=1, unique_items=True) + + + class UID(BaseModel): + __root__: int = Field(..., ge=0) + + + class Phone(BaseModel): + __root__: str = Field(..., min_length=3) + + + class Fax(BaseModel): + __root__: str = Field(..., min_length=3) + + + class User(BaseModel): + id: int = Field(..., ge=0) + name: str = Field(..., max_length=256) + tag: str | None = Field(None, max_length=64) + uid: UID + phones: list[Phone] | None = Field(None, max_items=10) + fax: list[Fax] | None = None + height: int | float | None = Field(None, ge=1.0, le=300.0) + weight: float | int | None = Field(None, ge=1.0, le=1000.0) + age: int | None = Field(None, gt=0, le=200) + rating: float | None = Field(None, gt=0.0, le=5.0) + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--disable-timestamp` {#disable-timestamp} + +Disable timestamp in generated file header for reproducible output. + +The `--disable-timestamp` flag configures the code generation behavior. + +**See also:** [CI/CD Integration](../ci-cd.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --disable-timestamp # (1)! + ``` + + 1. :material-arrow-left: `--disable-timestamp` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Info", + "type": "object", + "properties": { + "hostName": { + "type": "string", + "format": "hostname" + }, + "arn": { + "type": "string", + "pattern": "(^arn:([^:]*):([^:]*):([^:]*):(|\\*|[\\d]{12}):(.+)$)|^\\*$" + }, + "tel": { + "type": "string", + "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$" + }, + "comment": { + "type": "string", + "pattern": "[^\\x08\\f\\n\\r\\t\\\\a+.?'\"|()]+$" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pattern.json + + from __future__ import annotations + + from pydantic import BaseModel, constr + + + class Info(BaseModel): + hostName: ( + constr( + regex=r'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9])\Z' + ) + | None + ) = None + arn: ( + constr(regex=r'(^arn:([^:]*):([^:]*):([^:]*):(|\*|[\d]{12}):(.+)$)|^\*$') | None + ) = None + tel: constr(regex=r'^(\([0-9]{3}\))?[0-9]{3}-[0-9]{4}$') | None = None + comment: constr(regex=r'[^\x08\f\n\r\t\\a+.?\'"|()]+$') | None = None + ``` + +--- + +## `--enable-command-header` {#enable-command-header} + +Include command-line options in file header for reproducibility. + +The `--enable-command-header` flag adds the full command-line used to generate +the file to the header, making it easy to reproduce the generation. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --enable-command-header # (1)! + ``` + + 1. :material-arrow-left: `--enable-command-header` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + # command: datamodel-codegen [COMMAND] + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--enable-version-header` {#enable-version-header} + +Include tool version information in file header. + +The `--enable-version-header` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --enable-version-header # (1)! + ``` + + 1. :material-arrow-left: `--enable-version-header` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + # version: 0.0.0 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--extra-template-data` {#extra-template-data} + +Pass custom template variables from JSON file for code generation. + +The `--extra-template-data` flag allows you to provide additional variables +(from a JSON file) that can be used in custom templates to configure generated +model settings like Config classes, enabling customization beyond standard options. + +**See also:** [Custom Templates](../custom_template.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --extra-template-data openapi/extra_data.json # (1)! + ``` + + 1. :material-arrow-left: `--extra-template-data` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + === "Pydantic v1" + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, Field + + + class Pet(BaseModel): # 1 2, 1 2, this is just a pet + class Config: + arbitrary_types_allowed = True + + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + + === "Pydantic v2" + + ```python + # generated by datamodel-codegen: + # filename: api.yaml + # timestamp: 1985-10-26T08:21:00+00:00 + + from __future__ import annotations + + from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel + + + class Pet(BaseModel): # 1 2, 1 2, this is just a pet + model_config = ConfigDict( + arbitrary_types_allowed=True, + coerce_numbers_to_str=True, + ) + id: int + name: str + tag: str | None = None + + + class Pets(RootModel[list[Pet]]): + root: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(RootModel[list[User]]): + root: list[User] + + + class Id(RootModel[str]): + root: str + + + class Rules(RootModel[list[str]]): + root: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(RootModel[list[Api]]): + root: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +## `--formatters` {#formatters} + +Specify code formatters to apply to generated output. + +The `--formatters` flag specifies which code formatters to apply to +the generated Python code. Available formatters are: black, isort, +ruff, yapf, autopep8, autoflake. Default is [black, isort]. +Use this to customize formatting or disable formatters entirely. + +**See also:** [CI/CD Integration](../ci-cd.md), [Code Formatting](../formatting.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --formatters isort # (1)! + ``` + + 1. :material-arrow-left: `--formatters` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet_simple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--no-treat-dot-as-module` {#no-treat-dot-as-module} + +Keep dots in schema names as underscores for flat output. + +The `--no-treat-dot-as-module` flag prevents splitting dotted schema names. + +**See also:** [Module Structure and Exports](../module-exports.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --no-treat-dot-as-module # (1)! + ``` + + 1. :material-arrow-left: `--no-treat-dot-as-module` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + # model.schema.json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "User", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer" + } + }, + "required": ["name"] + } + ``` + + **Output:** + + ```python + # __init__.py + # generated by datamodel-codegen: + # filename: treat_dot_as_module_single + # timestamp: 2019-07-26T00:00:00+00:00 + + # model_schema.py + # generated by datamodel-codegen: + # filename: model.schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class User(BaseModel): + name: str + age: int | None = None + ``` + +--- + +## `--treat-dot-as-module` {#treat-dot-as-module} + +Treat dots in schema names as module separators. + +The `--treat-dot-as-module` flag configures the code generation behavior. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --treat-dot-as-module # (1)! + ``` + + 1. :material-arrow-left: `--treat-dot-as-module` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + # model.schema.json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "User", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer" + } + }, + "required": ["name"] + } + ``` + + **Output:** + + ```python + # __init__.py + # generated by datamodel-codegen: + # filename: treat_dot_as_module_single + # timestamp: 2019-07-26T00:00:00+00:00 + + # model/__init__.py + # generated by datamodel-codegen: + # filename: treat_dot_as_module_single + # timestamp: 2019-07-26T00:00:00+00:00 + + # model/schema.py + # generated by datamodel-codegen: + # filename: model.schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class User(BaseModel): + name: str + age: int | None = None + ``` + +--- + +## `--use-double-quotes` {#use-double-quotes} + +Use double quotes for string literals in generated code. + +The --use-double-quotes option formats all string literals in the generated +Python code with double quotes instead of the default single quotes. This +helps maintain consistency with codebases that prefer double-quote formatting. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-double-quotes # (1)! + ``` + + 1. :material-arrow-left: `--use-double-quotes` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$id": "https://example.com/schemas/MapState.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MapState", + "allOf": [ + { + "anyOf": [ + { + "type": "object", + "properties": { + "latitude": {"type": "number", "minimum": -90, "maximum": 90}, + "longitude": {"type": "number", "minimum": -180, "maximum": 180}, + "zoom": {"type": "number", "minimum": 0, "maximum": 25, "default": 0}, + "bearing": {"type": "number"}, + "pitch": {"type": "number", "minimum": 0, "exclusiveMaximum": 90}, + "dragRotate": {"type": "boolean"}, + "mapSplitMode": {"type": "string", "const": "SINGLE_MAP"}, + "isSplit": {"type": "boolean", "const": false, "default": false} + }, + "required": ["latitude", "longitude", "pitch", "mapSplitMode"] + }, + { + "type": "object", + "properties": { + "latitude": {"$ref": "#/allOf/0/anyOf/0/properties/latitude"}, + "longitude": {"$ref": "#/allOf/0/anyOf/0/properties/longitude"}, + "zoom": {"$ref": "#/allOf/0/anyOf/0/properties/zoom"}, + "bearing": {"$ref": "#/allOf/0/anyOf/0/properties/bearing"}, + "pitch": {"$ref": "#/allOf/0/anyOf/0/properties/pitch"}, + "dragRotate": {"$ref": "#/allOf/0/anyOf/0/properties/dragRotate"}, + "mapSplitMode": {"type": "string", "const": "SWIPE_COMPARE"}, + "isSplit": {"type": "boolean", "const": true, "default": true} + }, + "required": ["latitude", "longitude", "pitch", "mapSplitMode"] + } + ] + }, + { + "anyOf": [ + { + "type": "object", + "properties": { + "mapViewMode": {"type": "string", "const": "MODE_2D"} + }, + "required": ["mapViewMode"] + }, + { + "type": "object", + "properties": { + "mapViewMode": {"type": "string", "const": "MODE_3D"} + }, + "required": ["mapViewMode"] + } + ] + } + ] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: all_of_any_of_base_class_ref.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import Literal + + from pydantic import BaseModel, Field, confloat + + + class MapState1(BaseModel): + map_view_mode: Literal["MODE_2D"] = Field( + "MODE_2D", alias="mapViewMode", const=True + ) + + + class MapState2(BaseModel): + latitude: Latitude + longitude: Longitude + zoom: Zoom | None = Field(default_factory=lambda: Zoom.parse_obj(0)) + bearing: Bearing | None = None + pitch: Pitch + drag_rotate: DragRotate | None = Field(None, alias="dragRotate") + map_split_mode: Literal["SWIPE_COMPARE"] = Field( + "SWIPE_COMPARE", alias="mapSplitMode", const=True + ) + is_split: Literal[True] = Field(True, alias="isSplit", const=True) + + + class MapState3(BaseModel): + pass + + + class MapState4(MapState1, MapState3): + pass + + + class MapState5(MapState2, MapState3): + pass + + + class MapState6(MapState4): + pass + + + class MapState7(MapState5): + pass + + + class MapState(BaseModel): + __root__: MapState4 | MapState5 | MapState6 | MapState7 = Field( + ..., title="MapState" + ) + + + class Bearing(BaseModel): + __root__: float + + + class DragRotate(BaseModel): + __root__: bool + + + class Latitude(BaseModel): + __root__: confloat(ge=-90.0, le=90.0) + + + class Longitude(BaseModel): + __root__: confloat(ge=-180.0, le=180.0) + + + class Pitch(BaseModel): + __root__: confloat(ge=0.0, lt=90.0) + + + class Zoom(BaseModel): + __root__: confloat(ge=0.0, le=25.0) + ``` + +--- + +## `--use-exact-imports` {#use-exact-imports} + +Import exact types instead of modules. + +The `--use-exact-imports` flag changes import style from module imports +to exact type imports. For example, instead of `from . import foo` then +`foo.Bar`, it generates `from .foo import Bar`. This can make the generated +code more explicit and easier to read. + +Note: This option primarily affects modular output where imports between +modules are generated. For single-file output, the difference is minimal. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-exact-imports # (1)! + ``` + + 1. :material-arrow-left: `--use-exact-imports` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet_simple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--validators` {#validators} + +Add custom field validators to generated Pydantic v2 models. + +The `--validators` option takes a JSON file defining validators per model. +Each validator specifies the field(s) to validate, the validation function +to import, and optionally the mode (before/after/wrap/plain). +This allows injecting custom validation logic into generated models. + +**See also:** [Field Validators](../validators.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --validators tests/data/jsonschema/field_validators_config.json --output-model-type pydantic_v2.BaseModel --disable-timestamp # (1)! + ``` + + 1. :material-arrow-left: `--validators` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "User", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string", + "format": "email" + }, + "age": { + "type": "integer", + "minimum": 0 + } + }, + "required": ["name", "email"] + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: field_validators.json + + from __future__ import annotations + + from typing import Any + + from myapp.validators import validate_email, validate_name + from pydantic import BaseModel, EmailStr, ValidationInfo, conint, field_validator + + + class User(BaseModel): + name: str + email: EmailStr + age: conint(ge=0) | None = None + + @field_validator('name', mode='before') + @classmethod + def validate_name_validator(cls, v: Any, info: ValidationInfo) -> Any: + return validate_name(v, info) + + @field_validator('email', mode='after') + @classmethod + def validate_email_validator(cls, v: Any, info: ValidationInfo) -> Any: + return validate_email(v, info) + ``` + +--- + +## `--wrap-string-literal` {#wrap-string-literal} + +Wrap long string literals across multiple lines. + +The `--wrap-string-literal` flag breaks long string literals (like descriptions) +across multiple lines for better readability, instead of having very long +single-line strings in the generated code. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --wrap-string-literal # (1)! + ``` + + 1. :material-arrow-left: `--wrap-string-literal` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "LongDescription", + "type": "object", + "properties": { + "summary": { + "type": "string", + "description": "summary for object" + }, + "description": { + "type": "string", + "description": "datamodel-code-generator. This code generator creates pydantic model from an openapi file and others." + }, + "multi_line": { + "description": "datamodel-code-generator\nThis code generator creates pydantic model from an openapi file and others.\n\n\nSupported source types\nOpenAPI 3 (YAML/JSON, OpenAPI Data Type)\nJSON Schema (JSON Schema Core/JSON Schema Validation)\nJSON/YAML/CSV Data (it will be converted to JSON Schema)\nPython dictionary (it will be converted to JSON Schema)", + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: long_description.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class LongDescription(BaseModel): + summary: str | None = Field(None, description='summary for object') + description: str | None = Field( + None, + description=( + 'datamodel-code-generator. This code generator creates pydantic model from' + ' an openapi file and others.' + ), + ) + multi_line: str | None = Field( + None, + description=( + 'datamodel-code-generator\nThis code generator creates pydantic model from' + ' an openapi file and others.\n\n\nSupported source types\nOpenAPI 3' + ' (YAML/JSON, OpenAPI Data Type)\nJSON Schema (JSON Schema Core/JSON Schema' + ' Validation)\nJSON/YAML/CSV Data (it will be converted to JSON' + ' Schema)\nPython dictionary (it will be converted to JSON Schema)' + ), + ) + ``` + +--- + +--- + +# OpenAPI-only Options + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/openapi-only-options/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--include-path-parameters`](#include-path-parameters) | Include OpenAPI path parameters in generated parameter model... | +| [`--openapi-include-paths`](#openapi-include-paths) | Filter OpenAPI paths to include in model generation. | +| [`--openapi-scopes`](#openapi-scopes) | Specify OpenAPI scopes to generate (schemas, paths, paramete... | +| [`--read-only-write-only-model-type`](#read-only-write-only-model-type) | Generate separate request and response models for readOnly/w... | +| [`--use-operation-id-as-name`](#use-operation-id-as-name) | Use OpenAPI operationId as the generated function/class name... | +| [`--use-status-code-in-response-name`](#use-status-code-in-response-name) | Include HTTP status code in response model names. | +| [`--validation`](#validation) | Enable validation constraints (deprecated, use --field-const... | + +--- + +## `--include-path-parameters` {#include-path-parameters} + +Include OpenAPI path parameters in generated parameter models. + +The `--include-path-parameters` flag adds path parameters (like /users/{userId}) +to the generated request parameter models. By default, only query parameters +are included. Use this with `--openapi-scopes parameters` to generate parameter +models that include both path and query parameters. + +**See also:** [OpenAPI-Specific Options](../openapi-options.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --include-path-parameters --openapi-scopes schemas paths parameters # (1)! + ``` + + 1. :material-arrow-left: `--include-path-parameters` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: API with Path Parameters + paths: + /users/{userId}/posts/{postId}: + get: + summary: Get a specific post by user + operationId: getUserPost + parameters: + - name: userId + in: path + required: true + schema: + type: integer + - name: postId + in: path + required: true + schema: + type: string + - name: includeComments + in: query + required: false + schema: + type: boolean + responses: + '200': + description: A post + content: + application/json: + schema: + $ref: "#/components/schemas/Post" + components: + schemas: + Post: + type: object + properties: + id: + type: string + title: + type: string + content: + type: string + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: include_path_parameters.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Post(BaseModel): + id: str | None = None + title: str | None = None + content: str | None = None + + + class UsersUserIdPostsPostIdGetParameters(BaseModel): + userId: int + postId: str + includeComments: bool | None = None + ``` + +--- + +## `--openapi-include-paths` {#openapi-include-paths} + +Filter OpenAPI paths to include in model generation. + +The `--openapi-include-paths` flag allows filtering which paths are processed. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --openapi-scopes paths schemas --openapi-include-paths /pets* # (1)! + ``` + + 1. :material-arrow-left: `--openapi-include-paths` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + description: | + This description is for testing + multi-line + description + + servers: + - url: http://petstore.swagger.io/v1 + security: + - BearerAuth: [] + paths: + /pets: + $ref: '#/components/pathItems/Pets' + /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/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + put: + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + summary: update a pet + tags: + - pets + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/PetForm' + 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 + /food: + post: + summary: Create a food + tags: + - pets + requestBody: + required: true + content: + application/problem+json: + schema: + type: string + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/problem+json: + schema: + type: string + /food/{food_id}: + get: + summary: Info for a specific pet + operationId: showFoodById + tags: + - foods + parameters: + - name: food_id + in: path + description: The id of the food to retrieve + schema: + type: string + - name: message_texts + in: query + required: false + explode: true + schema: + type: array + items: + type: string + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: integer + examples: + example-1: + value: + - 0 + - 1 + - 3 + 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 + /foo: + get: + tags: + - foo + responses: + '200': + description: OK + content: + application/json: + schema: + type: string + parameters: + - $ref: '#/components/parameters/MyParam' + /bar: + post: + summary: Create a bar + tags: + - bar + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PetForm' + /user: + get: + tags: + - user + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + post: + tags: + - user + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + responses: + '201': + description: OK + /users: + get: + tags: + - user + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + post: + tags: + - user + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + responses: + '201': + description: OK + components: + parameters: + MyParam: + name: foo + in: query + schema: + type: string + securitySchemes: + BearerAuth: + type: http + scheme: bearer + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + PetForm: + title: PetForm + type: object + properties: + name: + type: string + age: + type: integer + pathItems: + Pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + security: [] + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + default: 0 + type: integer + format: int32 + - name: HomeAddress + in: query + required: false + schema: + default: 'Unknown' + type: string + - name: kind + in: query + required: false + schema: + default: dog + type: string + 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: + type: array + items: + - $ref: "#/components/schemas/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + tags: + - pets + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PetForm' + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: body_and_parameters.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Error(BaseModel): + code: int + message: str + + + class PetForm(BaseModel): + name: str | None = None + age: int | None = None + + + class PetsGetResponse(BaseModel): + __root__: list[Pet] + ``` + +--- + +## `--openapi-scopes` {#openapi-scopes} + +Specify OpenAPI scopes to generate (schemas, paths, parameters). + +The `--openapi-scopes` flag configures the code generation behavior. + +**See also:** [OpenAPI-Specific Options](../openapi-options.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --openapi-scopes paths schemas # (1)! + ``` + + 1. :material-arrow-left: `--openapi-scopes` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + description: | + This description is for testing + multi-line + description + + servers: + - url: http://petstore.swagger.io/v1 + security: + - BearerAuth: [] + paths: + /pets: + $ref: '#/components/pathItems/Pets' + /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/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + put: + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + summary: update a pet + tags: + - pets + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/PetForm' + 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 + /food: + post: + summary: Create a food + tags: + - pets + requestBody: + required: true + content: + application/problem+json: + schema: + type: string + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/problem+json: + schema: + type: string + /food/{food_id}: + get: + summary: Info for a specific pet + operationId: showFoodById + tags: + - foods + parameters: + - name: food_id + in: path + description: The id of the food to retrieve + schema: + type: string + - name: message_texts + in: query + required: false + explode: true + schema: + type: array + items: + type: string + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: integer + examples: + example-1: + value: + - 0 + - 1 + - 3 + 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 + /foo: + get: + tags: + - foo + responses: + '200': + description: OK + content: + application/json: + schema: + type: string + parameters: + - $ref: '#/components/parameters/MyParam' + /bar: + post: + summary: Create a bar + tags: + - bar + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PetForm' + /user: + get: + tags: + - user + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + post: + tags: + - user + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + responses: + '201': + description: OK + /users: + get: + tags: + - user + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + post: + tags: + - user + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: + timestamp: + type: string + format: date-time + name: + type: string + age: + type: string + required: + - name + - timestamp + responses: + '201': + description: OK + components: + parameters: + MyParam: + name: foo + in: query + schema: + type: string + securitySchemes: + BearerAuth: + type: http + scheme: bearer + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + PetForm: + title: PetForm + type: object + properties: + name: + type: string + age: + type: integer + pathItems: + Pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + security: [] + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + default: 0 + type: integer + format: int32 + - name: HomeAddress + in: query + required: false + schema: + default: 'Unknown' + type: string + - name: kind + in: query + required: false + schema: + default: dog + type: string + 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: + type: array + items: + - $ref: "#/components/schemas/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + tags: + - pets + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PetForm' + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: body_and_parameters.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from datetime import datetime + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Error(BaseModel): + code: int + message: str + + + class PetForm(BaseModel): + name: str | None = None + age: int | None = None + + + class PetsGetResponse(BaseModel): + __root__: list[Pet] + + + class FoodFoodIdGetResponse(BaseModel): + __root__: list[int] + + + class UserGetResponse(BaseModel): + timestamp: datetime + name: str + age: str | None = None + + + class UserPostRequest(BaseModel): + timestamp: datetime + name: str + age: str | None = None + + + class UsersGetResponseItem(BaseModel): + timestamp: datetime + name: str + age: str | None = None + + + class UsersGetResponse(BaseModel): + __root__: list[UsersGetResponseItem] + + + class UsersPostRequestItem(BaseModel): + timestamp: datetime + name: str + age: str | None = None + + + class UsersPostRequest(BaseModel): + __root__: list[UsersPostRequestItem] + ``` + +--- + +## `--read-only-write-only-model-type` {#read-only-write-only-model-type} + +Generate separate request and response models for readOnly/writeOnly fields. + +The `--read-only-write-only-model-type` option controls how models with readOnly or writeOnly +properties are generated. The 'request-response' mode creates separate Request and Response +variants for each schema that contains readOnly or writeOnly fields, allowing proper type +validation for API requests and responses without a shared base model. + +**See also:** [OpenAPI-Specific Options](../openapi-options.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --read-only-write-only-model-type request-response # (1)! + ``` + + 1. :material-arrow-left: `--read-only-write-only-model-type` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + title: Read Only Write Only Test API + version: "1.0" + paths: {} + components: + schemas: + User: + type: object + required: + - id + - name + - password + properties: + id: + type: integer + readOnly: true + name: + type: string + password: + type: string + writeOnly: true + created_at: + type: string + format: date-time + readOnly: true + secret_token: + type: string + writeOnly: true + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: read_only_write_only.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import AwareDatetime, BaseModel + + + class UserRequest(BaseModel): + name: str + password: str + secret_token: str | None = None + + + class UserResponse(BaseModel): + id: int + name: str + created_at: AwareDatetime | None = None + ``` + +--- + +## `--use-operation-id-as-name` {#use-operation-id-as-name} + +Use OpenAPI operationId as the generated function/class name. + +The `--use-operation-id-as-name` flag configures the code generation behavior. + +**See also:** [OpenAPI-Specific Options](../openapi-options.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-operation-id-as-name --openapi-scopes paths schemas parameters # (1)! + ``` + + 1. :material-arrow-left: `--use-operation-id-as-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + + + class ListPetsParametersQuery(BaseModel): + limit: int | None = None + ``` + +--- + +## `--use-status-code-in-response-name` {#use-status-code-in-response-name} + +Include HTTP status code in response model names. + +The `--use-status-code-in-response-name` flag includes the HTTP status code +in generated response model class names. Instead of generating ambiguous names +like ResourceGetResponse, ResourceGetResponse1, ResourceGetResponse2, it generates +clear names like ResourceGetResponse200, ResourceGetResponse400, ResourceGetResponseDefault. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --use-status-code-in-response-name --openapi-scopes schemas paths # (1)! + ``` + + 1. :material-arrow-left: `--use-status-code-in-response-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Status Code Response Name Test API + paths: + /resource: + get: + summary: Get a resource + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + id: + type: integer + name: + type: string + '400': + description: Bad request error + content: + application/json: + schema: + type: object + properties: + error: + type: string + code: + type: integer + 'default': + description: Unexpected error + content: + application/json: + schema: + type: object + properties: + message: + type: string + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: use_status_code_in_response_name.yaml + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class ResourceGetResponse200(BaseModel): + id: int | None = None + name: str | None = None + + + class ResourceGetResponse400(BaseModel): + error: str | None = None + code: int | None = None + + + class ResourceGetResponseDefault(BaseModel): + message: str | None = None + ``` + +--- + +## `--validation` {#validation} + +Enable validation constraints (deprecated, use --field-constraints). + +The `--validation` flag configures the code generation behavior. + +**Deprecated:** Use --field-constraints instead + +**See also:** [Field Constraints](../field-constraints.md), [OpenAPI-Specific Options](../openapi-options.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --validation # (1)! + ``` + + 1. :material-arrow-left: `--validation` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + 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:** + + ```python + # 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 + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + + class Pets(BaseModel): + __root__: list[Pet] + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Users(BaseModel): + __root__: list[User] + + + class Id(BaseModel): + __root__: str + + + class Rules(BaseModel): + __root__: list[str] + + + class Error(BaseModel): + code: int + message: str + + + class Api(BaseModel): + apiKey: str | None = Field( + None, description='To be used as a dataset parameter value' + ) + apiVersionNumber: str | None = Field( + None, description='To be used as a version parameter value' + ) + apiUrl: AnyUrl | None = Field( + None, description="The URL describing the dataset's fields" + ) + apiDocumentationUrl: AnyUrl | None = Field( + None, description='A URL to the API console for each API' + ) + + + class Apis(BaseModel): + __root__: list[Api] + + + class Event(BaseModel): + name: str | None = None + + + class Result(BaseModel): + event: Event | None = None + ``` + +--- + +--- + +# GraphQL-only Options + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/graphql-only-options/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--graphql-no-typename`](#graphql-no-typename) | Exclude __typename field from generated GraphQL models. | + +--- + +## `--graphql-no-typename` {#graphql-no-typename} + +Exclude __typename field from generated GraphQL models. + +The `--graphql-no-typename` flag prevents the generator from adding the +`typename__` field (aliased to `__typename`) to generated models. This is +useful when using generated models for GraphQL mutations, as servers typically +don't expect this field in input data. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --graphql-no-typename # (1)! + ``` + + 1. :material-arrow-left: `--graphql-no-typename` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```graphql + type Book { + id: ID! + title: String + } + + interface Node { + id: ID! + } + + input BookInput { + title: String! + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: no-typename.graphql + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from typing import TypeAlias + + from pydantic import BaseModel + + 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. + """ + + + 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. + """ + + + class Node(BaseModel): + id: ID + + + class Book(BaseModel): + id: ID + title: String | None = None + + + class BookInput(BaseModel): + title: String + ``` + +--- + +--- + +# General Options + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/general-options/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--all-exports-collision-strategy`](#all-exports-collision-strategy) | Handle name collisions when exporting recursive module hiera... | +| [`--all-exports-scope`](#all-exports-scope) | Generate __all__ exports for child modules in __init__.py fi... | +| [`--check`](#check) | Verify generated code matches existing output without modify... | +| [`--disable-warnings`](#disable-warnings) | Suppress warning messages during code generation. | +| [`--generate-cli-command`](#generate-cli-command) | Generate CLI command from pyproject.toml configuration. | +| [`--generate-pyproject-config`](#generate-pyproject-config) | Generate pyproject.toml configuration from CLI arguments. | +| [`--http-headers`](#http-headers) | Fetch schema from URL with custom HTTP headers. | +| [`--http-ignore-tls`](#http-ignore-tls) | Disable TLS certificate verification for HTTPS requests. | +| [`--http-query-parameters`](#http-query-parameters) | Add query parameters to HTTP requests for remote schemas. | +| [`--http-timeout`](#http-timeout) | Set timeout for HTTP requests to remote hosts. | +| [`--ignore-pyproject`](#ignore-pyproject) | Ignore pyproject.toml configuration file. | +| [`--module-split-mode`](#module-split-mode) | Split generated models into separate files, one per model cl... | +| [`--shared-module-name`](#shared-module-name) | Customize the name of the shared module for deduplicated mod... | +| [`--watch`](#watch) | Watch input file(s) for changes and regenerate output automa... | +| [`--watch-delay`](#watch-delay) | Set debounce delay in seconds for watch mode. | + +--- + +## `--all-exports-collision-strategy` {#all-exports-collision-strategy} + +Handle name collisions when exporting recursive module hierarchies. + +The `--all-exports-collision-strategy` flag determines how to resolve naming conflicts +when using `--all-exports-scope=recursive`. The 'minimal-prefix' strategy adds the +minimum module path prefix needed to disambiguate colliding names, while 'full-prefix' +uses the complete module path. Requires `--all-exports-scope=recursive`. + +**Related:** [`--all-exports-scope`](general-options.md#all-exports-scope) + +**See also:** [Module Structure and Exports](../module-exports.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --all-exports-scope recursive --all-exports-collision-strategy minimal-prefix # (1)! + ``` + + 1. :material-arrow-left: `--all-exports-collision-strategy` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Modular 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/collections.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/collections.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: + models.Species: + type: string + enum: + - dog + - cat + - snake + models.Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + species: + $ref: '#/components/schemas/models.Species' + models.User: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + collections.Pets: + type: array + items: + $ref: "#/components/schemas/models.Pet" + collections.Users: + type: array + items: + $ref: "#/components/schemas/models.User" + optional: + type: string + Id: + type: string + collections.Rules: + type: array + items: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + collections.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 + stage: + type: string + enum: [ + "test", + "dev", + "stg", + "prod" + ] + models.Event: + type: object + properties: + name: + anyOf: + - type: string + - type: number + - type: integer + - type: boolean + - type: object + - type: array + items: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/models.Event' + foo.bar.Thing: + properties: + attributes: + type: object + foo.bar.Thang: + properties: + attributes: + type: array + items: + type: object + foo.bar.Clone: + allOf: + - $ref: '#/components/schemas/foo.bar.Thing' + - type: object + properties: + others: + type: object + properties: + name: + type: string + + foo.Tea: + properties: + flavour: + type: string + id: + $ref: '#/components/schemas/Id' + Source: + properties: + country: + type: string + foo.Cocoa: + properties: + quality: + type: integer + bar.Field: + type: string + example: green + woo.boo.Chocolate: + properties: + flavour: + type: string + source: + $ref: '#/components/schemas/Source' + cocoa: + $ref: '#/components/schemas/foo.Cocoa' + field: + $ref: '#/components/schemas/bar.Field' + differentTea: + type: object + properties: + foo: + $ref: '#/components/schemas/foo.Tea' + nested: + $ref: '#/components/schemas/nested.foo.Tea' + nested.foo.Tea: + properties: + flavour: + type: string + id: + $ref: '#/components/schemas/Id' + self: + $ref: '#/components/schemas/nested.foo.Tea' + optional: + type: array + items: + $ref: '#/components/schemas/optional' + nested.foo.TeaClone: + properties: + flavour: + type: string + id: + $ref: '#/components/schemas/Id' + self: + $ref: '#/components/schemas/nested.foo.Tea' + optional: + type: array + items: + $ref: '#/components/schemas/optional' + nested.foo.List: + type: array + items: + $ref: '#/components/schemas/nested.foo.Tea' + ``` + + **Output:** + + ```python + # __init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from ._internal import DifferentTea, Error, Id, Optional, Result, Source + + __all__ = ["DifferentTea", "Error", "Id", "Optional", "Result", "Source"] + + # _internal.py + # generated by datamodel-codegen: + # filename: _internal + + from __future__ import annotations + + from pydantic import BaseModel + + from . import models + + + class Optional(BaseModel): + __root__: str + + + class Id(BaseModel): + __root__: str + + + class Error(BaseModel): + code: int + message: str + + + class Result(BaseModel): + event: models.Event | None = None + + + class Source(BaseModel): + country: str | None = None + + + class DifferentTea(BaseModel): + foo: Tea | None = None + nested: Tea_1 | None = None + + + class Tea(BaseModel): + flavour: str | None = None + id: Id | None = None + + + class Cocoa(BaseModel): + quality: int | None = None + + + class Tea_1(BaseModel): + flavour: str | None = None + id: Id | None = None + self: Tea_1 | None = None + optional: list[Optional] | None = None + + + class TeaClone(BaseModel): + flavour: str | None = None + id: Id | None = None + self: Tea_1 | None = None + optional: list[Optional] | None = None + + + class List(BaseModel): + __root__: list[Tea_1] + + + Tea_1.update_forward_refs() + + # bar.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class FieldModel(BaseModel): + __root__: str = Field(..., example='green') + + # collections.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from enum import Enum + + from pydantic import AnyUrl, BaseModel, Field + + from . import models + + + class Pets(BaseModel): + __root__: list[models.Pet] + + + class Users(BaseModel): + __root__: list[models.User] + + + class Rules(BaseModel): + __root__: list[str] + + + class Stage(Enum): + test = 'test' + dev = 'dev' + stg = 'stg' + prod = 'prod' + + + 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' + ) + stage: Stage | None = None + + + class Apis(BaseModel): + __root__: list[Api] + + # foo/__init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from .._internal import Cocoa, Tea + + __all__ = ["Cocoa", "Tea"] + + # foo/bar.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class Thing(BaseModel): + attributes: dict[str, Any] | None = None + + + class Thang(BaseModel): + attributes: list[dict[str, Any]] | None = None + + + class Others(BaseModel): + name: str | None = None + + + class Clone(Thing): + others: Others | None = None + + # models.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from enum import Enum + from typing import Any + + from pydantic import BaseModel + + + class Species(Enum): + dog = 'dog' + cat = 'cat' + snake = 'snake' + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + species: Species | None = None + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Event(BaseModel): + name: str | float | int | bool | dict[str, Any] | list[str] | None = None + + # nested/__init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + # nested/foo.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from .._internal import List + from .._internal import Tea_1 as Tea + from .._internal import TeaClone + + __all__ = ["List", "Tea", "TeaClone"] + + # woo/__init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from .boo import Chocolate + + __all__ = [ + "Chocolate", + ] + + # woo/boo.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from pydantic import BaseModel + + from .. import bar + from .._internal import Cocoa, Source + + + class Chocolate(BaseModel): + flavour: str | None = None + source: Source | None = None + cocoa: Cocoa | None = None + field: bar.FieldModel | None = None + ``` + +--- + +## `--all-exports-scope` {#all-exports-scope} + +Generate __all__ exports for child modules in __init__.py files. + +The `--all-exports-scope=children` flag adds __all__ to each __init__.py containing +exports from direct child modules. This improves IDE autocomplete and explicit exports. +Use 'recursive' to include all descendant exports with collision handling. + +**Related:** [`--all-exports-collision-strategy`](general-options.md#all-exports-collision-strategy) + +**See also:** [Module Structure and Exports](../module-exports.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --all-exports-scope children # (1)! + ``` + + 1. :material-arrow-left: `--all-exports-scope` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```yaml + openapi: "3.0.0" + info: + version: 1.0.0 + title: Modular 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/collections.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/collections.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: + models.Species: + type: string + enum: + - dog + - cat + - snake + models.Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + species: + $ref: '#/components/schemas/models.Species' + models.User: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + collections.Pets: + type: array + items: + $ref: "#/components/schemas/models.Pet" + collections.Users: + type: array + items: + $ref: "#/components/schemas/models.User" + optional: + type: string + Id: + type: string + collections.Rules: + type: array + items: + type: string + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string + collections.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 + stage: + type: string + enum: [ + "test", + "dev", + "stg", + "prod" + ] + models.Event: + type: object + properties: + name: + anyOf: + - type: string + - type: number + - type: integer + - type: boolean + - type: object + - type: array + items: + type: string + Result: + type: object + properties: + event: + $ref: '#/components/schemas/models.Event' + foo.bar.Thing: + properties: + attributes: + type: object + foo.bar.Thang: + properties: + attributes: + type: array + items: + type: object + foo.bar.Clone: + allOf: + - $ref: '#/components/schemas/foo.bar.Thing' + - type: object + properties: + others: + type: object + properties: + name: + type: string + + foo.Tea: + properties: + flavour: + type: string + id: + $ref: '#/components/schemas/Id' + Source: + properties: + country: + type: string + foo.Cocoa: + properties: + quality: + type: integer + bar.Field: + type: string + example: green + woo.boo.Chocolate: + properties: + flavour: + type: string + source: + $ref: '#/components/schemas/Source' + cocoa: + $ref: '#/components/schemas/foo.Cocoa' + field: + $ref: '#/components/schemas/bar.Field' + differentTea: + type: object + properties: + foo: + $ref: '#/components/schemas/foo.Tea' + nested: + $ref: '#/components/schemas/nested.foo.Tea' + nested.foo.Tea: + properties: + flavour: + type: string + id: + $ref: '#/components/schemas/Id' + self: + $ref: '#/components/schemas/nested.foo.Tea' + optional: + type: array + items: + $ref: '#/components/schemas/optional' + nested.foo.TeaClone: + properties: + flavour: + type: string + id: + $ref: '#/components/schemas/Id' + self: + $ref: '#/components/schemas/nested.foo.Tea' + optional: + type: array + items: + $ref: '#/components/schemas/optional' + nested.foo.List: + type: array + items: + $ref: '#/components/schemas/nested.foo.Tea' + ``` + + **Output:** + + ```python + # __init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from ._internal import DifferentTea, Error, Id, Optional, Result, Source + + __all__ = ["DifferentTea", "Error", "Id", "Optional", "Result", "Source"] + + # _internal.py + # generated by datamodel-codegen: + # filename: _internal + + from __future__ import annotations + + from pydantic import BaseModel + + from . import models + + + class Optional(BaseModel): + __root__: str + + + class Id(BaseModel): + __root__: str + + + class Error(BaseModel): + code: int + message: str + + + class Result(BaseModel): + event: models.Event | None = None + + + class Source(BaseModel): + country: str | None = None + + + class DifferentTea(BaseModel): + foo: Tea | None = None + nested: Tea_1 | None = None + + + class Tea(BaseModel): + flavour: str | None = None + id: Id | None = None + + + class Cocoa(BaseModel): + quality: int | None = None + + + class Tea_1(BaseModel): + flavour: str | None = None + id: Id | None = None + self: Tea_1 | None = None + optional: list[Optional] | None = None + + + class TeaClone(BaseModel): + flavour: str | None = None + id: Id | None = None + self: Tea_1 | None = None + optional: list[Optional] | None = None + + + class List(BaseModel): + __root__: list[Tea_1] + + + Tea_1.update_forward_refs() + + # bar.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class FieldModel(BaseModel): + __root__: str = Field(..., example='green') + + # collections.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from enum import Enum + + from pydantic import AnyUrl, BaseModel, Field + + from . import models + + + class Pets(BaseModel): + __root__: list[models.Pet] + + + class Users(BaseModel): + __root__: list[models.User] + + + class Rules(BaseModel): + __root__: list[str] + + + class Stage(Enum): + test = 'test' + dev = 'dev' + stg = 'stg' + prod = 'prod' + + + 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' + ) + stage: Stage | None = None + + + class Apis(BaseModel): + __root__: list[Api] + + # foo/__init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from .._internal import Cocoa, Tea + + __all__ = ["Cocoa", "Tea"] + + # foo/bar.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class Thing(BaseModel): + attributes: dict[str, Any] | None = None + + + class Thang(BaseModel): + attributes: list[dict[str, Any]] | None = None + + + class Others(BaseModel): + name: str | None = None + + + class Clone(Thing): + others: Others | None = None + + # models.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from enum import Enum + from typing import Any + + from pydantic import BaseModel + + + class Species(Enum): + dog = 'dog' + cat = 'cat' + snake = 'snake' + + + class Pet(BaseModel): + id: int + name: str + tag: str | None = None + species: Species | None = None + + + class User(BaseModel): + id: int + name: str + tag: str | None = None + + + class Event(BaseModel): + name: str | float | int | bool | dict[str, Any] | list[str] | None = None + + # nested/__init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + # nested/foo.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from .._internal import List + from .._internal import Tea_1 as Tea + from .._internal import TeaClone + + __all__ = ["List", "Tea", "TeaClone"] + + # woo/__init__.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from .boo import Chocolate + + __all__ = [ + "Chocolate", + ] + + # woo/boo.py + # generated by datamodel-codegen: + # filename: modular.yaml + + from __future__ import annotations + + from pydantic import BaseModel + + from .. import bar + from .._internal import Cocoa, Source + + + class Chocolate(BaseModel): + flavour: str | None = None + source: Source | None = None + cocoa: Cocoa | None = None + field: bar.FieldModel | None = None + ``` + +--- + +## `--check` {#check} + +Verify generated code matches existing output without modifying files. + +The `--check` flag compares the generated output with existing files and exits with +a non-zero status if they differ. Useful for CI/CD validation to ensure schemas +and generated code stay in sync. Works with both single files and directory outputs. + +**See also:** [CI/CD Integration](../ci-cd.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --disable-timestamp --check # (1)! + ``` + + 1. :material-arrow-left: `--check` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + ```python + # generated by datamodel-codegen: + # filename: person.json + + 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 = None + ``` + +--- + +## `--disable-warnings` {#disable-warnings} + +Suppress warning messages during code generation. + +The --disable-warnings option silences all warning messages that the generator +might emit during processing (e.g., about unsupported features, ambiguous schemas, +or potential issues). Useful for clean output in CI/CD pipelines. + +**See also:** [Model Reuse and Deduplication](../model-reuse.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --disable-warnings # (1)! + ``` + + 1. :material-arrow-left: `--disable-warnings` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "allOf": [ + { + "$ref": "#/definitions/Home" + }, + { + "$ref": "#/definitions/Kind" + }, + { + "$ref": "#/definitions/Id" + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + ], + "type": [ + "object" + ], + "properties": { + "name": { + "type": "string" + }, + "age": { + "type": "integer" + } + }, + "definitions": { + "Home": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "zip": { + "type": "string" + } + } + }, + "Kind": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + } + }, + "Id": { + "type": "object", + "properties": { + "id": { + "type": "integer" + } + } + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: all_of_with_object.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Home(BaseModel): + address: str | None = None + zip: str | None = None + + + class Kind(BaseModel): + description: str | None = None + + + class Id(BaseModel): + id: int | None = None + + + class Pet(Home, Kind, Id): + name: str | None = None + age: int | None = None + ``` + +--- + +## `--generate-cli-command` {#generate-cli-command} + +Generate CLI command from pyproject.toml configuration. + +The `--generate-cli-command` flag reads your pyproject.toml configuration +and outputs the equivalent CLI command. This is useful for debugging +configuration issues or sharing commands with others. + +**See also:** [pyproject.toml Configuration](../pyproject_toml.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --generate-cli-command # (1)! + ``` + + 1. :material-arrow-left: `--generate-cli-command` - the option documented here + +??? example "Examples" + + **Configuration (pyproject.toml):** + + ```toml + [tool.datamodel-codegen] + input = "schema.yaml" + output = "model.py" + ``` + + **Output:** + + ``` + datamodel-codegen --input schema.yaml --output model.py + ``` + +--- + +## `--generate-pyproject-config` {#generate-pyproject-config} + +Generate pyproject.toml configuration from CLI arguments. + +The `--generate-pyproject-config` flag outputs a pyproject.toml configuration +snippet based on the provided CLI arguments. This is useful for converting +a working CLI command into a reusable configuration file. + +**See also:** [pyproject.toml Configuration](../pyproject_toml.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --generate-pyproject-config --input schema.yaml --output model.py # (1)! + ``` + + 1. :material-arrow-left: `--generate-pyproject-config` - the option documented here + +??? example "Examples" + + **Output:** + + ``` + [tool.datamodel-codegen] + input = "schema.yaml" + output = "model.py" + ``` + +--- + +## `--http-headers` {#http-headers} + +Fetch schema from URL with custom HTTP headers. + +The `--url` flag specifies a remote URL to fetch the schema from instead of +a local file. The `--http-headers` flag adds custom HTTP headers to the request, +useful for authentication (e.g., Bearer tokens) or custom API requirements. +Format: `HeaderName:HeaderValue`. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --url https://api.example.com/schema.json --http-headers "Authorization:Bearer token" # (1)! + ``` + + 1. :material-arrow-left: `--http-headers` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: https://api.example.com/schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--http-ignore-tls` {#http-ignore-tls} + +Disable TLS certificate verification for HTTPS requests. + +The `--http-ignore-tls` flag disables SSL/TLS certificate verification +when fetching schemas from HTTPS URLs. This is useful for development +environments with self-signed certificates. Not recommended for production. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --url https://api.example.com/schema.json --http-ignore-tls # (1)! + ``` + + 1. :material-arrow-left: `--http-ignore-tls` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: https://api.example.com/schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--http-query-parameters` {#http-query-parameters} + +Add query parameters to HTTP requests for remote schemas. + +The `--http-query-parameters` flag adds query parameters to HTTP requests +when fetching schemas from URLs. Useful for APIs that require version +or format parameters. Format: `key=value`. Multiple parameters can be +specified: `--http-query-parameters version=v2 format=json`. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --url https://api.example.com/schema.json --http-query-parameters version=v2 format=json # (1)! + ``` + + 1. :material-arrow-left: `--http-query-parameters` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: https://api.example.com/schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--http-timeout` {#http-timeout} + +Set timeout for HTTP requests to remote hosts. + +The `--http-timeout` flag sets the timeout in seconds for HTTP requests +when fetching schemas from URLs. Useful for slow servers or large schemas. +Default is 30 seconds. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --url https://api.example.com/schema.json --http-timeout 60 # (1)! + ``` + + 1. :material-arrow-left: `--http-timeout` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: https://api.example.com/schema.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--ignore-pyproject` {#ignore-pyproject} + +Ignore pyproject.toml configuration file. + +The `--ignore-pyproject` flag tells datamodel-codegen to ignore any +[tool.datamodel-codegen] configuration in pyproject.toml. This is useful +when you want to override project defaults with CLI arguments, or when +testing without project configuration. + +**See also:** [pyproject.toml Configuration](../pyproject_toml.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --ignore-pyproject # (1)! + ``` + + 1. :material-arrow-left: `--ignore-pyproject` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "firstName": {"type": "string"}, + "lastName": {"type": "string"} + } + } + ``` + + **Output:** + + === "With Option" + + ```python + # generated by datamodel-codegen: + # filename: schema.json + + from __future__ import annotations + + from pydantic import BaseModel + + + class Model(BaseModel): + firstName: str | None = None + lastName: str | None = None + ``` + + === "Without Option" + + ```python + # generated by datamodel-codegen: + # filename: schema.json + + from __future__ import annotations + + from pydantic import BaseModel, Field + + + class Model(BaseModel): + first_name: str | None = Field(None, alias='firstName') + last_name: str | None = Field(None, alias='lastName') + ``` + +--- + +## `--module-split-mode` {#module-split-mode} + +Split generated models into separate files, one per model class. + +The `--module-split-mode=single` flag generates each model class in its own file, +named after the class in snake_case. Use with `--all-exports-scope=recursive` to +create an __init__.py that re-exports all models for convenient imports. + +**Related:** [`--all-exports-scope`](general-options.md#all-exports-scope), [`--use-exact-imports`](template-customization.md#use-exact-imports) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --module-split-mode single --all-exports-scope recursive --use-exact-imports # (1)! + ``` + + 1. :material-arrow-left: `--module-split-mode` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "User": { + "type": "object", + "properties": { + "id": {"type": "integer"}, + "name": {"type": "string"} + } + }, + "Order": { + "type": "object", + "properties": { + "id": {"type": "integer"}, + "user": {"$ref": "#/definitions/User"} + } + } + } + } + ``` + + **Output:** + + ```python + # __init__.py + # generated by datamodel-codegen: + # filename: input.json + + from __future__ import annotations + + from .model import Model + from .order import Order + from .user import User + + __all__ = [ + "Model", + "Order", + "User", + ] + + # model.py + # generated by datamodel-codegen: + # filename: input.json + + from __future__ import annotations + + from typing import Any + + from pydantic import BaseModel + + + class Model(BaseModel): + __root__: Any + + # order.py + # generated by datamodel-codegen: + # filename: input.json + + from __future__ import annotations + + from pydantic import BaseModel + + from .user import User + + + class Order(BaseModel): + id: int | None = None + user: User | None = None + + # user.py + # generated by datamodel-codegen: + # filename: input.json + + from __future__ import annotations + + from pydantic import BaseModel + + + class User(BaseModel): + id: int | None = None + name: str | None = None + ``` + +--- + +## `--shared-module-name` {#shared-module-name} + +Customize the name of the shared module for deduplicated models. + +The `--shared-module-name` flag sets the name of the shared module created +when using `--reuse-model` with `--reuse-scope=tree`. This module contains +deduplicated models that are referenced from multiple files. Default is +`shared`. Use this if your schema already has a file named `shared`. + +Note: This option only affects modular output with tree-level model reuse. + +**See also:** [Model Reuse and Deduplication](../model-reuse.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --shared-module-name my_shared # (1)! + ``` + + 1. :material-arrow-left: `--shared-module-name` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Pet", + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + ``` + + **Output:** + + ```python + # generated by datamodel-codegen: + # filename: pet_simple.json + # timestamp: 2019-07-26T00:00:00+00:00 + + from __future__ import annotations + + from pydantic import BaseModel + + + class Pet(BaseModel): + id: int | None = None + name: str | None = None + tag: str | None = None + ``` + +--- + +## `--watch` {#watch} + +Watch input file(s) for changes and regenerate output automatically. + +The `--watch` flag enables continuous file monitoring mode. When enabled, +datamodel-codegen watches the input file or directory for changes and +automatically regenerates the output whenever changes are detected. +Press Ctrl+C to stop watching. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --watch --check # (1)! + ``` + + 1. :material-arrow-left: `--watch` - the option documented here + +!!! warning "Requires extra dependency" + + The watch feature requires the `watch` extra: + + ```bash + pip install 'datamodel-code-generator[watch]' + ``` + +??? example "Examples" + + === "JSON Schema" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + ``` + Error: --watch and --check cannot be used together + ``` + + === "unknown" + + **Output:** + + ``` + Error: --watch requires --input file path + ``` + +--- + +## `--watch-delay` {#watch-delay} + +Set debounce delay in seconds for watch mode. + +The `--watch-delay` option configures the debounce interval (default: 0.5 seconds) +for watch mode. This prevents multiple regenerations when files are rapidly +modified in succession. The delay ensures that after the last file change, +the generator waits the specified time before regenerating. + +**Related:** [`--watch`](general-options.md#watch) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --watch --watch-delay 1.5 # (1)! + ``` + + 1. :material-arrow-left: `--watch-delay` - the option documented here + +??? example "Examples" + + **Input Schema:** + + ```json + { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": ["string", "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:** + + ``` + Watching + ``` + +--- + +--- + +# Utility Options + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/utility-options/ + +## ๐Ÿ“‹ Options + +| Option | Description | +|--------|-------------| +| [`--debug`](#debug) | Show debug messages during code generation | +| [`--generate-prompt`](#generate-prompt) | Generate a prompt for consulting LLMs about CLI options | +| [`--help`](#help) | Show help message and exit | +| [`--no-color`](#no-color) | Disable colorized output | +| [`--profile`](#profile) | Use a named profile from pyproject.toml | +| [`--version`](#version) | Show program version and exit | + +--- + +## `--debug` {#debug} + +Show debug messages during code generation. + +Enables verbose debug output to help troubleshoot issues with schema parsing +or code generation. Requires the `debug` extra to be installed. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --debug # (1)! + ``` + + 1. :material-arrow-left: `--debug` - the option documented here + +!!! warning "Requires extra dependency" + + The debug feature requires the `debug` extra: + + ```bash + pip install 'datamodel-code-generator[debug]' + ``` + +--- + +## `--generate-prompt` {#generate-prompt} + +Generate a prompt for consulting LLMs about CLI options. + +Outputs a formatted prompt containing your current options, all available +options by category, and full help text. Pipe to CLI LLM tools or copy +to clipboard for web-based LLM chats. + +**See also:** [LLM Integration](../llm-integration.md) for detailed usage examples + +!!! tip "Usage" + + ```bash + datamodel-codegen --generate-prompt # (1)! + datamodel-codegen --generate-prompt "How do I generate strict types?" # (2)! + ``` + + 1. :material-arrow-left: `--generate-prompt` - generate prompt without a question + 2. :material-arrow-left: Include a specific question in the prompt + +??? example "Quick Examples" + + **Pipe to CLI tools:** + ```bash + datamodel-codegen --generate-prompt | claude -p # Claude Code + datamodel-codegen --generate-prompt | codex exec # OpenAI Codex + ``` + + **Copy to clipboard:** + ```bash + datamodel-codegen --generate-prompt | pbcopy # macOS + datamodel-codegen --generate-prompt | xclip -selection clipboard # Linux + datamodel-codegen --generate-prompt | clip.exe # WSL2 + ``` + +--- + +## `--help` {#help} + +Show help message and exit. + +Displays all available command-line options with their descriptions and default values. + +**Aliases:** `-h` + +!!! tip "Usage" + + ```bash + datamodel-codegen --help # (1)! + ``` + + 1. :material-arrow-left: `--help` - the option documented here + +??? example "Output" + + ```text + usage: datamodel-codegen [-h] [--input INPUT] [--url URL] ... + + Generate Python data models from schema files. + + options: + -h, --help show this help message and exit + --input INPUT Input file path (default: stdin) + ... + ``` + +--- + +## `--no-color` {#no-color} + +Disable colorized output. + +By default, datamodel-codegen uses colored output for better readability. +Use this option to disable colors, which is useful for CI/CD pipelines +or when redirecting output to files. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --no-color # (1)! + ``` + + 1. :material-arrow-left: `--no-color` - the option documented here + +!!! note "Environment variable" + + You can also disable colors by setting the `NO_COLOR` environment variable: + + ```bash + NO_COLOR=1 datamodel-codegen --input schema.json + ``` + +--- + +## `--profile` {#profile} + +Use a named profile from pyproject.toml configuration. + +Profiles allow you to define multiple named configurations in your pyproject.toml +file. Each profile can override the default settings with its own set of options. + +**Related:** [pyproject.toml Configuration](../pyproject_toml.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --profile strict # (1)! + ``` + + 1. :material-arrow-left: `--profile` - the option documented here + +??? example "Configuration (pyproject.toml)" + + ```toml + [tool.datamodel-codegen] + # Default configuration + output-model-type = "pydantic_v2.BaseModel" + + [tool.datamodel-codegen.profiles.strict] + # Strict profile with additional options + strict-types = ["str", "int", "float", "bool"] + strict-nullable = true + + [tool.datamodel-codegen.profiles.legacy] + # Legacy profile for Pydantic v1 + output-model-type = "pydantic.BaseModel" + ``` + + Use profiles: + + ```bash + # Use the strict profile + datamodel-codegen --input schema.json --profile strict + + # Use the legacy profile + datamodel-codegen --input schema.json --profile legacy + ``` + +--- + +## `--version` {#version} + +Show program version and exit. + +Displays the installed version of datamodel-code-generator. + +!!! tip "Usage" + + ```bash + datamodel-codegen --version # (1)! + ``` + + 1. :material-arrow-left: `--version` - the option documented here + +??? example "Output" + + ```text + datamodel-codegen version: 0.x.x + ``` + +--- + +--- + +# Quick Reference + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/quick-reference/ + +All CLI options in one page for easy **Ctrl+F** searching. + +๐Ÿ‘† Click any option to see detailed documentation with examples. + +--- + +```text +datamodel-codegen [OPTIONS] +``` + +## ๐Ÿ“‚ All Options by Category + +### ๐Ÿ“ Base Options + +| Option | Description | +|--------|-------------| +| [`--encoding`](base-options.md#encoding) | Specify character encoding for input and output files. | +| [`--input`](base-options.md#input) | Specify the input schema file path. | +| [`--input-file-type`](base-options.md#input-file-type) | Specify the input file type for code generation. | +| [`--input-model`](base-options.md#input-model) | Import a Python type or dict schema from a module. | +| [`--input-model-ref-strategy`](base-options.md#input-model-ref-strategy) | Strategy for referenced types when using --input-model. | +| [`--output`](base-options.md#output) | Specify the destination path for generated Python code. | +| [`--url`](base-options.md#url) | Fetch schema from URL with custom HTTP headers. | + +### ๐Ÿ”ง Typing Customization + +| Option | Description | +|--------|-------------| +| [`--allof-class-hierarchy`](typing-customization.md#allof-class-hierarchy) | Controls how allOf schemas are represented in the generated class hierarchy. | +| [`--allof-merge-mode`](typing-customization.md#allof-merge-mode) | Merge constraints from root model references in allOf schemas. | +| [`--disable-future-imports`](typing-customization.md#disable-future-imports) | Prevent automatic addition of __future__ imports in generated code. | +| [`--enum-field-as-literal`](typing-customization.md#enum-field-as-literal) | Convert all enum fields to Literal types instead of Enum classes. | +| [`--enum-field-as-literal-map`](typing-customization.md#enum-field-as-literal-map) | Override enum/literal generation per-field via JSON mapping. | +| [`--ignore-enum-constraints`](typing-customization.md#ignore-enum-constraints) | Ignore enum constraints and use base string type instead of Enum classes. | +| [`--no-use-specialized-enum`](typing-customization.md#no-use-specialized-enum) | Disable specialized Enum classes for Python 3.11+ code generation. | +| [`--no-use-standard-collections`](typing-customization.md#no-use-standard-collections) | Use typing.Dict/List instead of built-in dict/list for container types. | +| [`--no-use-union-operator`](typing-customization.md#no-use-union-operator) | Use Union[X, Y] / Optional[X] instead of X | Y union operator. | +| [`--output-date-class`](typing-customization.md#output-date-class) | Specify date class type for date schema fields. | +| [`--output-datetime-class`](typing-customization.md#output-datetime-class) | Specify datetime class type for date-time schema fields. | +| [`--strict-types`](typing-customization.md#strict-types) | Enable strict type validation for specified Python types. | +| [`--type-mappings`](typing-customization.md#type-mappings) | Override default type mappings for schema formats. | +| [`--type-overrides`](typing-customization.md#type-overrides) | Replace schema model types with custom Python types via JSON mapping. | +| [`--use-annotated`](typing-customization.md#use-annotated) | Use typing.Annotated for Field() with constraints. | +| [`--use-decimal-for-multiple-of`](typing-customization.md#use-decimal-for-multiple-of) | Generate Decimal types for fields with multipleOf constraint. | +| [`--use-generic-container-types`](typing-customization.md#use-generic-container-types) | Use generic container types (Sequence, Mapping) for type hinting. | +| [`--use-non-positive-negative-number-constrained-types`](typing-customization.md#use-non-positive-negative-number-constrained-types) | Use NonPositive/NonNegative types for number constraints. | +| [`--use-pendulum`](typing-customization.md#use-pendulum) | Use pendulum types for date/time fields instead of datetime module. | +| [`--use-root-model-type-alias`](typing-customization.md#use-root-model-type-alias) | Generate RootModel as type alias format for better mypy support. | +| [`--use-specialized-enum`](typing-customization.md#use-specialized-enum) | Generate StrEnum/IntEnum for string/integer enums (Python 3.11+). | +| [`--use-standard-collections`](typing-customization.md#use-standard-collections) | Use built-in dict/list instead of typing.Dict/List. | +| [`--use-standard-primitive-types`](typing-customization.md#use-standard-primitive-types) | Use Python standard library types for string formats instead of str. | +| [`--use-tuple-for-fixed-items`](typing-customization.md#use-tuple-for-fixed-items) | Generate tuple types for arrays with items array syntax. | +| [`--use-type-alias`](typing-customization.md#use-type-alias) | Use TypeAlias instead of root models for type definitions (experimental). | +| [`--use-union-operator`](typing-customization.md#use-union-operator) | Use | operator for Union types (PEP 604). | +| [`--use-unique-items-as-set`](typing-customization.md#use-unique-items-as-set) | Generate set types for arrays with uniqueItems constraint. | + +### ๐Ÿท๏ธ Field Customization + +| Option | Description | +|--------|-------------| +| [`--aliases`](field-customization.md#aliases) | Apply custom field and class name aliases from JSON file. | +| [`--capitalize-enum-members`](field-customization.md#capitalize-enum-members) | Capitalize enum member names to UPPER_CASE format. | +| [`--default-values`](field-customization.md#default-values) | Override field default values from external JSON file. | +| [`--empty-enum-field-name`](field-customization.md#empty-enum-field-name) | Name for empty string enum field values. | +| [`--extra-fields`](field-customization.md#extra-fields) | Configure how generated models handle extra fields not defined in schema. | +| [`--field-constraints`](field-customization.md#field-constraints) | Generate Field() with validation constraints from schema. | +| [`--field-extra-keys`](field-customization.md#field-extra-keys) | Include specific extra keys in Field() definitions. | +| [`--field-extra-keys-without-x-prefix`](field-customization.md#field-extra-keys-without-x-prefix) | Include schema extension keys in Field() without requiring 'x-' prefix. | +| [`--field-include-all-keys`](field-customization.md#field-include-all-keys) | Include all schema keys in Field() json_schema_extra. | +| [`--field-type-collision-strategy`](field-customization.md#field-type-collision-strategy) | Rename type class instead of field when names collide (Pydantic v2 only). | +| [`--no-alias`](field-customization.md#no-alias) | Disable Field alias generation for non-Python-safe property names. | +| [`--original-field-name-delimiter`](field-customization.md#original-field-name-delimiter) | Specify delimiter for original field names when using snake-case conversion. | +| [`--remove-special-field-name-prefix`](field-customization.md#remove-special-field-name-prefix) | Remove the special prefix from field names. | +| [`--set-default-enum-member`](field-customization.md#set-default-enum-member) | Set the first enum member as the default value for enum fields. | +| [`--snake-case-field`](field-customization.md#snake-case-field) | Convert field names to snake_case format. | +| [`--special-field-name-prefix`](field-customization.md#special-field-name-prefix) | Prefix to add to special field names (like reserved keywords). | +| [`--use-attribute-docstrings`](field-customization.md#use-attribute-docstrings) | Generate field descriptions as attribute docstrings instead of Field description... | +| [`--use-enum-values-in-discriminator`](field-customization.md#use-enum-values-in-discriminator) | Use enum values in discriminator mappings for union types. | +| [`--use-field-description`](field-customization.md#use-field-description) | Include schema descriptions as Field docstrings. | +| [`--use-field-description-example`](field-customization.md#use-field-description-example) | Add field examples to docstrings. | +| [`--use-inline-field-description`](field-customization.md#use-inline-field-description) | Add field descriptions as inline comments. | +| [`--use-schema-description`](field-customization.md#use-schema-description) | Use schema description as class docstring. | +| [`--use-serialization-alias`](field-customization.md#use-serialization-alias) | Use serialization_alias instead of alias for field aliasing (Pydantic v2 only). | +| [`--use-title-as-name`](field-customization.md#use-title-as-name) | Use schema title as the generated class name. | + +### ๐Ÿ—๏ธ Model Customization + +| Option | Description | +|--------|-------------| +| [`--allow-extra-fields`](model-customization.md#allow-extra-fields) | Allow extra fields in generated Pydantic models (extra='allow'). | +| [`--allow-population-by-field-name`](model-customization.md#allow-population-by-field-name) | Allow Pydantic model population by field name (not just alias). | +| [`--base-class`](model-customization.md#base-class) | Specify a custom base class for generated models. | +| [`--base-class-map`](model-customization.md#base-class-map) | Specify different base classes for specific models via JSON mapping. | +| [`--class-name`](model-customization.md#class-name) | Override the auto-generated class name with a custom name. | +| [`--class-name-affix-scope`](model-customization.md#class-name-affix-scope) | Control which classes receive the prefix/suffix. | +| [`--class-name-prefix`](model-customization.md#class-name-prefix) | Add a prefix to all generated class names. | +| [`--class-name-suffix`](model-customization.md#class-name-suffix) | Add a suffix to all generated class names. | +| [`--collapse-reuse-models`](model-customization.md#collapse-reuse-models) | Collapse duplicate models by replacing references instead of inheritance. | +| [`--collapse-root-models`](model-customization.md#collapse-root-models) | Inline root model definitions instead of creating separate wrapper classes. | +| [`--collapse-root-models-name-strategy`](model-customization.md#collapse-root-models-name-strategy) | Select which name to keep when collapsing root models with object references. | +| [`--dataclass-arguments`](model-customization.md#dataclass-arguments) | Customize dataclass decorator arguments via JSON dictionary. | +| [`--duplicate-name-suffix`](model-customization.md#duplicate-name-suffix) | Customize suffix for duplicate model names. | +| [`--enable-faux-immutability`](model-customization.md#enable-faux-immutability) | Enable faux immutability in Pydantic v1 models (allow_mutation=False). | +| [`--force-optional`](model-customization.md#force-optional) | Force all fields to be Optional regardless of required status. | +| [`--frozen-dataclasses`](model-customization.md#frozen-dataclasses) | Generate frozen dataclasses with optional keyword-only fields. | +| [`--keep-model-order`](model-customization.md#keep-model-order) | Keep model definition order as specified in schema. | +| [`--keyword-only`](model-customization.md#keyword-only) | Generate dataclasses with keyword-only fields (Python 3.10+). | +| [`--model-extra-keys`](model-customization.md#model-extra-keys) | Add model-level schema extensions to ConfigDict json_schema_extra. | +| [`--model-extra-keys-without-x-prefix`](model-customization.md#model-extra-keys-without-x-prefix) | Strip x- prefix from model-level schema extensions and add to ConfigDict json_sc... | +| [`--naming-strategy`](model-customization.md#naming-strategy) | Use parent-prefixed naming strategy for duplicate model names. | +| [`--output-model-type`](model-customization.md#output-model-type) | Select the output model type (Pydantic v1/v2, dataclasses, TypedDict, msgspec). | +| [`--parent-scoped-naming`](model-customization.md#parent-scoped-naming) | Namespace models by their parent scope to avoid naming conflicts. | +| [`--reuse-model`](model-customization.md#reuse-model) | Reuse identical model definitions instead of generating duplicates. | +| [`--reuse-scope`](model-customization.md#reuse-scope) | Scope for model reuse detection (root or tree). | +| [`--skip-root-model`](model-customization.md#skip-root-model) | Skip generation of root model when schema contains nested definitions. | +| [`--strict-nullable`](model-customization.md#strict-nullable) | Treat default field as a non-nullable field. | +| [`--strip-default-none`](model-customization.md#strip-default-none) | Remove fields with None as default value from generated models. | +| [`--target-pydantic-version`](model-customization.md#target-pydantic-version) | Target Pydantic version for generated code compatibility. | +| [`--target-python-version`](model-customization.md#target-python-version) | Target Python version for generated code syntax and imports. | +| [`--union-mode`](model-customization.md#union-mode) | Union mode for combining anyOf/oneOf schemas (smart or left_to_right). | +| [`--use-default`](model-customization.md#use-default) | Use default values from schema in generated models. | +| [`--use-default-factory-for-optional-nested-models`](model-customization.md#use-default-factory-for-optional-nested-models) | Generate default_factory for optional nested model fields. | +| [`--use-default-kwarg`](model-customization.md#use-default-kwarg) | Use default= keyword argument instead of positional argument for fields with def... | +| [`--use-frozen-field`](model-customization.md#use-frozen-field) | Generate frozen (immutable) field definitions for readOnly properties. | +| [`--use-generic-base-class`](model-customization.md#use-generic-base-class) | Generate a shared base class with model configuration to avoid repetition (DRY).... | +| [`--use-one-literal-as-default`](model-customization.md#use-one-literal-as-default) | Use single literal value as default when enum has only one option. | +| [`--use-serialize-as-any`](model-customization.md#use-serialize-as-any) | Wrap fields with subtypes in Pydantic's SerializeAsAny. | +| [`--use-subclass-enum`](model-customization.md#use-subclass-enum) | Generate typed Enum subclasses for enums with specific field types. | + +### ๐ŸŽจ Template Customization + +| Option | Description | +|--------|-------------| +| [`--additional-imports`](template-customization.md#additional-imports) | Add custom imports to generated output files. | +| [`--class-decorators`](template-customization.md#class-decorators) | Add custom decorators to generated model classes. | +| [`--custom-file-header`](template-customization.md#custom-file-header) | Add custom header text to the generated file. | +| [`--custom-file-header-path`](template-customization.md#custom-file-header-path) | Add custom header content from file to generated code. | +| [`--custom-formatters`](template-customization.md#custom-formatters) | Apply custom Python code formatters to generated output. | +| [`--custom-formatters-kwargs`](template-customization.md#custom-formatters-kwargs) | Pass custom arguments to custom formatters via JSON file. | +| [`--custom-template-dir`](template-customization.md#custom-template-dir) | Use custom Jinja2 templates for model generation. | +| [`--disable-appending-item-suffix`](template-customization.md#disable-appending-item-suffix) | Disable appending 'Item' suffix to array item types. | +| [`--disable-timestamp`](template-customization.md#disable-timestamp) | Disable timestamp in generated file header for reproducible output. | +| [`--enable-command-header`](template-customization.md#enable-command-header) | Include command-line options in file header for reproducibility. | +| [`--enable-version-header`](template-customization.md#enable-version-header) | Include tool version information in file header. | +| [`--extra-template-data`](template-customization.md#extra-template-data) | Pass custom template variables from JSON file for code generation. | +| [`--formatters`](template-customization.md#formatters) | Specify code formatters to apply to generated output. | +| [`--no-treat-dot-as-module`](template-customization.md#no-treat-dot-as-module) | Keep dots in schema names as underscores for flat output. | +| [`--treat-dot-as-module`](template-customization.md#treat-dot-as-module) | Treat dots in schema names as module separators. | +| [`--use-double-quotes`](template-customization.md#use-double-quotes) | Use double quotes for string literals in generated code. | +| [`--use-exact-imports`](template-customization.md#use-exact-imports) | Import exact types instead of modules. | +| [`--validators`](template-customization.md#validators) | Add custom field validators to generated Pydantic v2 models. | +| [`--wrap-string-literal`](template-customization.md#wrap-string-literal) | Wrap long string literals across multiple lines. | + +### ๐Ÿ“˜ OpenAPI-only Options + +| Option | Description | +|--------|-------------| +| [`--include-path-parameters`](openapi-only-options.md#include-path-parameters) | Include OpenAPI path parameters in generated parameter models. | +| [`--openapi-include-paths`](openapi-only-options.md#openapi-include-paths) | Filter OpenAPI paths to include in model generation. | +| [`--openapi-scopes`](openapi-only-options.md#openapi-scopes) | Specify OpenAPI scopes to generate (schemas, paths, parameters). | +| [`--read-only-write-only-model-type`](openapi-only-options.md#read-only-write-only-model-type) | Generate separate request and response models for readOnly/writeOnly fields. | +| [`--use-operation-id-as-name`](openapi-only-options.md#use-operation-id-as-name) | Use OpenAPI operationId as the generated function/class name. | +| [`--use-status-code-in-response-name`](openapi-only-options.md#use-status-code-in-response-name) | Include HTTP status code in response model names. | +| [`--validation`](openapi-only-options.md#validation) | Enable validation constraints (deprecated, use --field-constraints). | + +### ๐Ÿ“‹ GraphQL-only Options + +| Option | Description | +|--------|-------------| +| [`--graphql-no-typename`](graphql-only-options.md#graphql-no-typename) | Exclude __typename field from generated GraphQL models. | + +### โš™๏ธ General Options + +| Option | Description | +|--------|-------------| +| [`--all-exports-collision-strategy`](general-options.md#all-exports-collision-strategy) | Handle name collisions when exporting recursive module hierarchies. | +| [`--all-exports-scope`](general-options.md#all-exports-scope) | Generate __all__ exports for child modules in __init__.py files. | +| [`--check`](general-options.md#check) | Verify generated code matches existing output without modifying files. | +| [`--disable-warnings`](general-options.md#disable-warnings) | Suppress warning messages during code generation. | +| [`--generate-cli-command`](general-options.md#generate-cli-command) | Generate CLI command from pyproject.toml configuration. | +| [`--generate-pyproject-config`](general-options.md#generate-pyproject-config) | Generate pyproject.toml configuration from CLI arguments. | +| [`--http-headers`](general-options.md#http-headers) | Fetch schema from URL with custom HTTP headers. | +| [`--http-ignore-tls`](general-options.md#http-ignore-tls) | Disable TLS certificate verification for HTTPS requests. | +| [`--http-query-parameters`](general-options.md#http-query-parameters) | Add query parameters to HTTP requests for remote schemas. | +| [`--http-timeout`](general-options.md#http-timeout) | Set timeout for HTTP requests to remote hosts. | +| [`--ignore-pyproject`](general-options.md#ignore-pyproject) | Ignore pyproject.toml configuration file. | +| [`--module-split-mode`](general-options.md#module-split-mode) | Split generated models into separate files, one per model class. | +| [`--shared-module-name`](general-options.md#shared-module-name) | Customize the name of the shared module for deduplicated models. | +| [`--watch`](general-options.md#watch) | Watch input file(s) for changes and regenerate output automatically. | +| [`--watch-delay`](general-options.md#watch-delay) | Set debounce delay in seconds for watch mode. | + +### ๐Ÿ“ Utility Options + +| Option | Description | +|--------|-------------| +| [`--debug`](utility-options.md#debug) | Show debug messages during code generation | +| [`--generate-prompt`](utility-options.md#generate-prompt) | Generate a prompt for consulting LLMs about CLI options | +| [`--help`](utility-options.md#help) | Show help message and exit | +| [`--no-color`](utility-options.md#no-color) | Disable colorized output | +| [`--profile`](utility-options.md#profile) | Use a named profile from pyproject.toml | +| [`--version`](utility-options.md#version) | Show program version and exit | + +--- + +## ๐Ÿ”ค Alphabetical Index + +All options sorted alphabetically: + +- [`--additional-imports`](template-customization.md#additional-imports) - Add custom imports to generated output files. +- [`--aliases`](field-customization.md#aliases) - Apply custom field and class name aliases from JSON file. +- [`--all-exports-collision-strategy`](general-options.md#all-exports-collision-strategy) - Handle name collisions when exporting recursive module hiera... +- [`--all-exports-scope`](general-options.md#all-exports-scope) - Generate __all__ exports for child modules in __init__.py fi... +- [`--allof-class-hierarchy`](typing-customization.md#allof-class-hierarchy) - Controls how allOf schemas are represented in the generated ... +- [`--allof-merge-mode`](typing-customization.md#allof-merge-mode) - Merge constraints from root model references in allOf schema... +- [`--allow-extra-fields`](model-customization.md#allow-extra-fields) - Allow extra fields in generated Pydantic models (extra='allo... +- [`--allow-population-by-field-name`](model-customization.md#allow-population-by-field-name) - Allow Pydantic model population by field name (not just alia... +- [`--base-class`](model-customization.md#base-class) - Specify a custom base class for generated models. +- [`--base-class-map`](model-customization.md#base-class-map) - Specify different base classes for specific models via JSON ... +- [`--capitalize-enum-members`](field-customization.md#capitalize-enum-members) - Capitalize enum member names to UPPER_CASE format. +- [`--check`](general-options.md#check) - Verify generated code matches existing output without modify... +- [`--class-decorators`](template-customization.md#class-decorators) - Add custom decorators to generated model classes. +- [`--class-name`](model-customization.md#class-name) - Override the auto-generated class name with a custom name. +- [`--class-name-affix-scope`](model-customization.md#class-name-affix-scope) - Control which classes receive the prefix/suffix. +- [`--class-name-prefix`](model-customization.md#class-name-prefix) - Add a prefix to all generated class names. +- [`--class-name-suffix`](model-customization.md#class-name-suffix) - Add a suffix to all generated class names. +- [`--collapse-reuse-models`](model-customization.md#collapse-reuse-models) - Collapse duplicate models by replacing references instead of... +- [`--collapse-root-models`](model-customization.md#collapse-root-models) - Inline root model definitions instead of creating separate w... +- [`--collapse-root-models-name-strategy`](model-customization.md#collapse-root-models-name-strategy) - Select which name to keep when collapsing root models with o... +- [`--custom-file-header`](template-customization.md#custom-file-header) - Add custom header text to the generated file. +- [`--custom-file-header-path`](template-customization.md#custom-file-header-path) - Add custom header content from file to generated code. +- [`--custom-formatters`](template-customization.md#custom-formatters) - Apply custom Python code formatters to generated output. +- [`--custom-formatters-kwargs`](template-customization.md#custom-formatters-kwargs) - Pass custom arguments to custom formatters via JSON file. +- [`--custom-template-dir`](template-customization.md#custom-template-dir) - Use custom Jinja2 templates for model generation. +- [`--dataclass-arguments`](model-customization.md#dataclass-arguments) - Customize dataclass decorator arguments via JSON dictionary. +- [`--debug`](utility-options.md#debug) - Show debug messages during code generation +- [`--default-values`](field-customization.md#default-values) - Override field default values from external JSON file. +- [`--disable-appending-item-suffix`](template-customization.md#disable-appending-item-suffix) - Disable appending 'Item' suffix to array item types. +- [`--disable-future-imports`](typing-customization.md#disable-future-imports) - Prevent automatic addition of __future__ imports in generate... +- [`--disable-timestamp`](template-customization.md#disable-timestamp) - Disable timestamp in generated file header for reproducible ... +- [`--disable-warnings`](general-options.md#disable-warnings) - Suppress warning messages during code generation. +- [`--duplicate-name-suffix`](model-customization.md#duplicate-name-suffix) - Customize suffix for duplicate model names. +- [`--empty-enum-field-name`](field-customization.md#empty-enum-field-name) - Name for empty string enum field values. +- [`--enable-command-header`](template-customization.md#enable-command-header) - Include command-line options in file header for reproducibil... +- [`--enable-faux-immutability`](model-customization.md#enable-faux-immutability) - Enable faux immutability in Pydantic v1 models (allow_mutati... +- [`--enable-version-header`](template-customization.md#enable-version-header) - Include tool version information in file header. +- [`--encoding`](base-options.md#encoding) - Specify character encoding for input and output files. +- [`--enum-field-as-literal`](typing-customization.md#enum-field-as-literal) - Convert all enum fields to Literal types instead of Enum cla... +- [`--enum-field-as-literal-map`](typing-customization.md#enum-field-as-literal-map) - Override enum/literal generation per-field via JSON mapping. +- [`--extra-fields`](field-customization.md#extra-fields) - Configure how generated models handle extra fields not defin... +- [`--extra-template-data`](template-customization.md#extra-template-data) - Pass custom template variables from JSON file for code gener... +- [`--field-constraints`](field-customization.md#field-constraints) - Generate Field() with validation constraints from schema. +- [`--field-extra-keys`](field-customization.md#field-extra-keys) - Include specific extra keys in Field() definitions. +- [`--field-extra-keys-without-x-prefix`](field-customization.md#field-extra-keys-without-x-prefix) - Include schema extension keys in Field() without requiring '... +- [`--field-include-all-keys`](field-customization.md#field-include-all-keys) - Include all schema keys in Field() json_schema_extra. +- [`--field-type-collision-strategy`](field-customization.md#field-type-collision-strategy) - Rename type class instead of field when names collide (Pydan... +- [`--force-optional`](model-customization.md#force-optional) - Force all fields to be Optional regardless of required statu... +- [`--formatters`](template-customization.md#formatters) - Specify code formatters to apply to generated output. +- [`--frozen-dataclasses`](model-customization.md#frozen-dataclasses) - Generate frozen dataclasses with optional keyword-only field... +- [`--generate-cli-command`](general-options.md#generate-cli-command) - Generate CLI command from pyproject.toml configuration. +- [`--generate-prompt`](utility-options.md#generate-prompt) - Generate a prompt for consulting LLMs about CLI options +- [`--generate-pyproject-config`](general-options.md#generate-pyproject-config) - Generate pyproject.toml configuration from CLI arguments. +- [`--graphql-no-typename`](graphql-only-options.md#graphql-no-typename) - Exclude __typename field from generated GraphQL models. +- [`--help`](utility-options.md#help) - Show help message and exit +- [`--http-headers`](general-options.md#http-headers) - Fetch schema from URL with custom HTTP headers. +- [`--http-ignore-tls`](general-options.md#http-ignore-tls) - Disable TLS certificate verification for HTTPS requests. +- [`--http-query-parameters`](general-options.md#http-query-parameters) - Add query parameters to HTTP requests for remote schemas. +- [`--http-timeout`](general-options.md#http-timeout) - Set timeout for HTTP requests to remote hosts. +- [`--ignore-enum-constraints`](typing-customization.md#ignore-enum-constraints) - Ignore enum constraints and use base string type instead of ... +- [`--ignore-pyproject`](general-options.md#ignore-pyproject) - Ignore pyproject.toml configuration file. +- [`--include-path-parameters`](openapi-only-options.md#include-path-parameters) - Include OpenAPI path parameters in generated parameter model... +- [`--input`](base-options.md#input) - Specify the input schema file path. +- [`--input-file-type`](base-options.md#input-file-type) - Specify the input file type for code generation. +- [`--input-model`](base-options.md#input-model) - Import a Python type or dict schema from a module. +- [`--input-model-ref-strategy`](base-options.md#input-model-ref-strategy) - Strategy for referenced types when using --input-model. +- [`--keep-model-order`](model-customization.md#keep-model-order) - Keep model definition order as specified in schema. +- [`--keyword-only`](model-customization.md#keyword-only) - Generate dataclasses with keyword-only fields (Python 3.10+)... +- [`--model-extra-keys`](model-customization.md#model-extra-keys) - Add model-level schema extensions to ConfigDict json_schema_... +- [`--model-extra-keys-without-x-prefix`](model-customization.md#model-extra-keys-without-x-prefix) - Strip x- prefix from model-level schema extensions and add t... +- [`--module-split-mode`](general-options.md#module-split-mode) - Split generated models into separate files, one per model cl... +- [`--naming-strategy`](model-customization.md#naming-strategy) - Use parent-prefixed naming strategy for duplicate model name... +- [`--no-alias`](field-customization.md#no-alias) - Disable Field alias generation for non-Python-safe property ... +- [`--no-color`](utility-options.md#no-color) - Disable colorized output +- [`--no-treat-dot-as-module`](template-customization.md#no-treat-dot-as-module) - Keep dots in schema names as underscores for flat output. +- [`--no-use-specialized-enum`](typing-customization.md#no-use-specialized-enum) - Disable specialized Enum classes for Python 3.11+ code gener... +- [`--no-use-standard-collections`](typing-customization.md#no-use-standard-collections) - Use typing.Dict/List instead of built-in dict/list for conta... +- [`--no-use-union-operator`](typing-customization.md#no-use-union-operator) - Use Union[X, Y] / Optional[X] instead of X | Y union operato... +- [`--openapi-include-paths`](openapi-only-options.md#openapi-include-paths) - Filter OpenAPI paths to include in model generation. +- [`--openapi-scopes`](openapi-only-options.md#openapi-scopes) - Specify OpenAPI scopes to generate (schemas, paths, paramete... +- [`--original-field-name-delimiter`](field-customization.md#original-field-name-delimiter) - Specify delimiter for original field names when using snake-... +- [`--output`](base-options.md#output) - Specify the destination path for generated Python code. +- [`--output-date-class`](typing-customization.md#output-date-class) - Specify date class type for date schema fields. +- [`--output-datetime-class`](typing-customization.md#output-datetime-class) - Specify datetime class type for date-time schema fields. +- [`--output-model-type`](model-customization.md#output-model-type) - Select the output model type (Pydantic v1/v2, dataclasses, T... +- [`--parent-scoped-naming`](model-customization.md#parent-scoped-naming) - Namespace models by their parent scope to avoid naming confl... +- [`--profile`](utility-options.md#profile) - Use a named profile from pyproject.toml +- [`--read-only-write-only-model-type`](openapi-only-options.md#read-only-write-only-model-type) - Generate separate request and response models for readOnly/w... +- [`--remove-special-field-name-prefix`](field-customization.md#remove-special-field-name-prefix) - Remove the special prefix from field names. +- [`--reuse-model`](model-customization.md#reuse-model) - Reuse identical model definitions instead of generating dupl... +- [`--reuse-scope`](model-customization.md#reuse-scope) - Scope for model reuse detection (root or tree). +- [`--set-default-enum-member`](field-customization.md#set-default-enum-member) - Set the first enum member as the default value for enum fiel... +- [`--shared-module-name`](general-options.md#shared-module-name) - Customize the name of the shared module for deduplicated mod... +- [`--skip-root-model`](model-customization.md#skip-root-model) - Skip generation of root model when schema contains nested de... +- [`--snake-case-field`](field-customization.md#snake-case-field) - Convert field names to snake_case format. +- [`--special-field-name-prefix`](field-customization.md#special-field-name-prefix) - Prefix to add to special field names (like reserved keywords... +- [`--strict-nullable`](model-customization.md#strict-nullable) - Treat default field as a non-nullable field. +- [`--strict-types`](typing-customization.md#strict-types) - Enable strict type validation for specified Python types. +- [`--strip-default-none`](model-customization.md#strip-default-none) - Remove fields with None as default value from generated mode... +- [`--target-pydantic-version`](model-customization.md#target-pydantic-version) - Target Pydantic version for generated code compatibility. +- [`--target-python-version`](model-customization.md#target-python-version) - Target Python version for generated code syntax and imports. +- [`--treat-dot-as-module`](template-customization.md#treat-dot-as-module) - Treat dots in schema names as module separators. +- [`--type-mappings`](typing-customization.md#type-mappings) - Override default type mappings for schema formats. +- [`--type-overrides`](typing-customization.md#type-overrides) - Replace schema model types with custom Python types via JSON... +- [`--union-mode`](model-customization.md#union-mode) - Union mode for combining anyOf/oneOf schemas (smart or left_... +- [`--url`](base-options.md#url) - Fetch schema from URL with custom HTTP headers. +- [`--use-annotated`](typing-customization.md#use-annotated) - Use typing.Annotated for Field() with constraints. +- [`--use-attribute-docstrings`](field-customization.md#use-attribute-docstrings) - Generate field descriptions as attribute docstrings instead ... +- [`--use-decimal-for-multiple-of`](typing-customization.md#use-decimal-for-multiple-of) - Generate Decimal types for fields with multipleOf constraint... +- [`--use-default`](model-customization.md#use-default) - Use default values from schema in generated models. +- [`--use-default-factory-for-optional-nested-models`](model-customization.md#use-default-factory-for-optional-nested-models) - Generate default_factory for optional nested model fields. +- [`--use-default-kwarg`](model-customization.md#use-default-kwarg) - Use default= keyword argument instead of positional argument... +- [`--use-double-quotes`](template-customization.md#use-double-quotes) - Use double quotes for string literals in generated code. +- [`--use-enum-values-in-discriminator`](field-customization.md#use-enum-values-in-discriminator) - Use enum values in discriminator mappings for union types. +- [`--use-exact-imports`](template-customization.md#use-exact-imports) - Import exact types instead of modules. +- [`--use-field-description`](field-customization.md#use-field-description) - Include schema descriptions as Field docstrings. +- [`--use-field-description-example`](field-customization.md#use-field-description-example) - Add field examples to docstrings. +- [`--use-frozen-field`](model-customization.md#use-frozen-field) - Generate frozen (immutable) field definitions for readOnly p... +- [`--use-generic-base-class`](model-customization.md#use-generic-base-class) - Generate a shared base class with model configuration to avo... +- [`--use-generic-container-types`](typing-customization.md#use-generic-container-types) - Use generic container types (Sequence, Mapping) for type hin... +- [`--use-inline-field-description`](field-customization.md#use-inline-field-description) - Add field descriptions as inline comments. +- [`--use-non-positive-negative-number-constrained-types`](typing-customization.md#use-non-positive-negative-number-constrained-types) - Use NonPositive/NonNegative types for number constraints. +- [`--use-one-literal-as-default`](model-customization.md#use-one-literal-as-default) - Use single literal value as default when enum has only one o... +- [`--use-operation-id-as-name`](openapi-only-options.md#use-operation-id-as-name) - Use OpenAPI operationId as the generated function/class name... +- [`--use-pendulum`](typing-customization.md#use-pendulum) - Use pendulum types for date/time fields instead of datetime ... +- [`--use-root-model-type-alias`](typing-customization.md#use-root-model-type-alias) - Generate RootModel as type alias format for better mypy supp... +- [`--use-schema-description`](field-customization.md#use-schema-description) - Use schema description as class docstring. +- [`--use-serialization-alias`](field-customization.md#use-serialization-alias) - Use serialization_alias instead of alias for field aliasing ... +- [`--use-serialize-as-any`](model-customization.md#use-serialize-as-any) - Wrap fields with subtypes in Pydantic's SerializeAsAny. +- [`--use-specialized-enum`](typing-customization.md#use-specialized-enum) - Generate StrEnum/IntEnum for string/integer enums (Python 3.... +- [`--use-standard-collections`](typing-customization.md#use-standard-collections) - Use built-in dict/list instead of typing.Dict/List. +- [`--use-standard-primitive-types`](typing-customization.md#use-standard-primitive-types) - Use Python standard library types for string formats instead... +- [`--use-status-code-in-response-name`](openapi-only-options.md#use-status-code-in-response-name) - Include HTTP status code in response model names. +- [`--use-subclass-enum`](model-customization.md#use-subclass-enum) - Generate typed Enum subclasses for enums with specific field... +- [`--use-title-as-name`](field-customization.md#use-title-as-name) - Use schema title as the generated class name. +- [`--use-tuple-for-fixed-items`](typing-customization.md#use-tuple-for-fixed-items) - Generate tuple types for arrays with items array syntax. +- [`--use-type-alias`](typing-customization.md#use-type-alias) - Use TypeAlias instead of root models for type definitions (e... +- [`--use-union-operator`](typing-customization.md#use-union-operator) - Use | operator for Union types (PEP 604). +- [`--use-unique-items-as-set`](typing-customization.md#use-unique-items-as-set) - Generate set types for arrays with uniqueItems constraint. +- [`--validation`](openapi-only-options.md#validation) - Enable validation constraints (deprecated, use --field-const... +- [`--validators`](template-customization.md#validators) - Add custom field validators to generated Pydantic v2 models. +- [`--version`](utility-options.md#version) - Show program version and exit +- [`--watch`](general-options.md#watch) - Watch input file(s) for changes and regenerate output automa... +- [`--watch-delay`](general-options.md#watch-delay) - Set debounce delay in seconds for watch mode. +- [`--wrap-string-literal`](template-customization.md#wrap-string-literal) - Wrap long string literals across multiple lines. + +--- + +# Help + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/help/ + +## `--help` {#help} + +Show help message and exit. + +Displays all available command-line options with their descriptions and default values. + +**Aliases:** `-h` + +!!! tip "Usage" + + ```bash + datamodel-codegen --help # (1)! + ``` + + 1. :material-arrow-left: `--help` - the option documented here + +??? example "Output" + + ```text + usage: datamodel-codegen [-h] [--input INPUT] [--url URL] ... + + Generate Python data models from schema files. + + options: + -h, --help show this help message and exit + --input INPUT Input file path (default: stdin) + ... + ``` + +--- + +# Version + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/version/ + +## `--version` {#version} + +Show program version and exit. + +Displays the installed version of datamodel-code-generator. + +!!! tip "Usage" + + ```bash + datamodel-codegen --version # (1)! + ``` + + 1. :material-arrow-left: `--version` - the option documented here + +??? example "Output" + + ```text + datamodel-codegen version: 0.x.x + ``` + +--- + +# Debug + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/debug/ + +## `--debug` {#debug} + +Show debug messages during code generation. + +Enables verbose debug output to help troubleshoot issues with schema parsing +or code generation. Requires the `debug` extra to be installed. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --debug # (1)! + ``` + + 1. :material-arrow-left: `--debug` - the option documented here + +!!! warning "Requires extra dependency" + + The debug feature requires the `debug` extra: + + ```bash + pip install 'datamodel-code-generator[debug]' + ``` + +--- + +# Profile + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/profile/ + +## `--profile` {#profile} + +Use a named profile from pyproject.toml configuration. + +Profiles allow you to define multiple named configurations in your pyproject.toml +file. Each profile can override the default settings with its own set of options. + +**Related:** [pyproject.toml Configuration](../../pyproject_toml.md) + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --profile strict # (1)! + ``` + + 1. :material-arrow-left: `--profile` - the option documented here + +??? example "Configuration (pyproject.toml)" + + ```toml + [tool.datamodel-codegen] + # Default configuration + output-model-type = "pydantic_v2.BaseModel" + + [tool.datamodel-codegen.profiles.strict] + # Strict profile with additional options + strict-types = ["str", "int", "float", "bool"] + strict-nullable = true + + [tool.datamodel-codegen.profiles.legacy] + # Legacy profile for Pydantic v1 + output-model-type = "pydantic.BaseModel" + ``` + + Use profiles: + + ```bash + # Use the strict profile + datamodel-codegen --input schema.json --profile strict + + # Use the legacy profile + datamodel-codegen --input schema.json --profile legacy + ``` + +--- + +# No Color + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/no-color/ + +## `--no-color` {#no-color} + +Disable colorized output. + +By default, datamodel-codegen uses colored output for better readability. +Use this option to disable colors, which is useful for CI/CD pipelines +or when redirecting output to files. + +!!! tip "Usage" + + ```bash + datamodel-codegen --input schema.json --no-color # (1)! + ``` + + 1. :material-arrow-left: `--no-color` - the option documented here + +!!! note "Environment variable" + + You can also disable colors by setting the `NO_COLOR` environment variable: + + ```bash + NO_COLOR=1 datamodel-codegen --input schema.json + ``` + +--- + +# Generate Prompt + +Source: https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/generate-prompt/ + +## `--generate-prompt` {#generate-prompt} + +Generate a prompt for consulting LLMs about CLI options. + +Outputs a formatted prompt containing your current options, all available +options by category, and full help text. Pipe to CLI LLM tools or copy +to clipboard for web-based LLM chats. + +**See also:** [LLM Integration](../../llm-integration.md) for detailed usage examples + +!!! tip "Usage" + + ```bash + datamodel-codegen --generate-prompt # (1)! + datamodel-codegen --generate-prompt "How do I generate strict types?" # (2)! + ``` + + 1. :material-arrow-left: `--generate-prompt` - generate prompt without a question + 2. :material-arrow-left: Include a specific question in the prompt + +??? example "Quick Examples" + + **Pipe to CLI tools:** + ```bash + datamodel-codegen --generate-prompt | claude -p # Claude Code + datamodel-codegen --generate-prompt | codex exec # OpenAI Codex + ``` + + **Copy to clipboard:** + ```bash + datamodel-codegen --generate-prompt | pbcopy # macOS + datamodel-codegen --generate-prompt | xclip -selection clipboard # Linux + datamodel-codegen --generate-prompt | clip.exe # WSL2 + ``` + +--- + +# Supported Input Formats + +Source: https://datamodel-code-generator.koxudaxi.dev/supported-data-types/ + +This code generator supports the following input formats: + +- OpenAPI 3 (YAML/JSON, [OpenAPI Data Type](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#data-types)); +- JSON Schema ([JSON Schema Core](http://json-schema.org/draft/2019-09/json-schema-validation.html) /[JSON Schema Validation](http://json-schema.org/draft/2019-09/json-schema-validation.html)); +- JSON/YAML Data (it will be converted to JSON Schema); +- Python dictionary (it will be converted to JSON Schema); +- GraphQL schema ([GraphQL Schemas and Types](https://graphql.org/learn/schema/)); + +## ๐Ÿ“˜ OpenAPI 3 and JSON Schema {#openapi-3-and-json-schema} + +Below are the data types and features recognized by datamodel-code-generator for OpenAPI 3 and JSON Schema. + +## โœ… Implemented data types and features + +### ๐Ÿ“Š Data Types +- string (supported keywords: pattern/minLength/maxLength) +- number (supported keywords: maximum/exclusiveMaximum/minimum/exclusiveMinimum/multipleOf) +- integer (supported keywords: maximum/exclusiveMaximum/minimum/exclusiveMinimum/multipleOf) +- boolean +- array +- object + +### ๐Ÿ“ String Formats +- date +- datetime +- time +- password +- email (requires [`email-validator`](https://github.com/JoshData/python-email-validator)) +- idn-email (requires [`email-validator`](https://github.com/JoshData/python-email-validator)) +- path +- uuid (uuid1/uuid2/uuid3/uuid4/uuid5) +- ulid (requires [`python-ulid`](https://github.com/mdomke/python-ulid)) +- ipv4 +- ipv6 +- hostname +- decimal +- uri + +### ๐Ÿ”— Other schema +- enum (as enum.Enum or typing.Literal) +- allOf (as Multiple inheritance) +- anyOf (as typing.Union) +- oneOf (as typing.Union) +- $ref ([http extra](index.md#http-extra-option) is required when resolving $ref for remote files.) +- $id (for [JSONSchema](https://json-schema.org/understanding-json-schema/structuring.html#id)) + +--- + +# Generate from OpenAPI + +Source: https://datamodel-code-generator.koxudaxi.dev/openapi/ + +Generate Pydantic models from OpenAPI 3 schema definitions. + +## ๐Ÿš€ Quick Start + +```bash +datamodel-codegen --input api.yaml --input-file-type openapi --output model.py +``` + +## ๐Ÿ“ Example + +
+api.yaml + +```yaml +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 + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + 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" + /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" +components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string +``` + +
+ +**โœจ Generated model.py:** + +```python +# generated by datamodel-codegen: +# filename: api.yaml + +from __future__ import annotations + +from pydantic import BaseModel, RootModel + + +class Pet(BaseModel): + id: int + name: str + tag: str | None = None + + +class Pets(RootModel[list[Pet]]): + root: list[Pet] + + +class Error(BaseModel): + code: int + message: str +``` + +--- + +## ๐Ÿ“– readOnly / writeOnly Properties + +OpenAPI 3.x supports `readOnly` and `writeOnly` property annotations: + +- ๐Ÿ“ค **readOnly**: Property is only returned in responses (e.g., `id`, `created_at`) +- ๐Ÿ“ฅ **writeOnly**: Property is only sent in requests (e.g., `password`) + +### โš™๏ธ Option: `--read-only-write-only-model-type` + +This option generates separate Request/Response models based on these annotations. + +| Value | Description | +|-------|-------------| +| (not set) | Default. No special handling (backward compatible) | +| `request-response` | Generate only Request/Response models (no base model) | +| `all` | Generate base model + Request + Response models | + +### ๐Ÿ“‹ Example Schema + +```yaml +openapi: "3.0.0" +info: + title: User API + version: "1.0" +paths: {} +components: + schemas: + User: + type: object + required: + - id + - name + properties: + id: + type: integer + readOnly: true # Server-generated, not in requests + name: + type: string + password: + type: string + writeOnly: true # Client-only, not in responses + created_at: + type: string + format: date-time + readOnly: true +``` + +### โœจ Generated Output + +```bash +datamodel-codegen --input user.yaml --input-file-type openapi \ + --output-model-type pydantic_v2.BaseModel \ + --read-only-write-only-model-type all +``` + +```python +from pydantic import BaseModel +from typing import Optional +from datetime import datetime + +# ๐Ÿ“ฅ Request model: excludes readOnly fields (id, created_at) +class UserRequest(BaseModel): + name: str + password: Optional[str] = None + +# ๐Ÿ“ค Response model: excludes writeOnly fields (password) +class UserResponse(BaseModel): + id: int + name: str + created_at: Optional[datetime] = None + +# ๐Ÿ“ฆ Base model: contains all fields +class User(BaseModel): + id: int + name: str + password: Optional[str] = None + created_at: Optional[datetime] = None +``` + +### ๐ŸŽฏ Usage Patterns + +| Use Case | Recommended Option | Generated Models | +|----------|-------------------|------------------| +| API client validation | `request-response` | `UserRequest`, `UserResponse` | +| Database ORM mapping | (not set) | `User` | +| Both client & ORM | `all` | `User`, `UserRequest`, `UserResponse` | + +### ๐Ÿ”— Behavior with allOf Inheritance + +When using `allOf` with `$ref`, fields from all referenced schemas are flattened into Request/Response models: + +```yaml +components: + schemas: + Timestamps: + type: object + properties: + created_at: + type: string + format: date-time + readOnly: true + + User: + allOf: + - $ref: "#/components/schemas/Timestamps" + - type: object + properties: + name: + type: string +``` + +Generated `UserRequest` will exclude `created_at` (readOnly from Timestamps). + +### โš ๏ธ Collision Handling + +If a schema named `UserRequest` or `UserResponse` already exists, the generated model will be named `UserRequestModel` or `UserResponseModel` to avoid conflicts. + +### ๐Ÿ“ค Supported Output Formats + +This option works with all output formats: + +- `pydantic.BaseModel` / `pydantic_v2.BaseModel` +- `dataclasses.dataclass` +- `typing.TypedDict` +- `msgspec.Struct` + +### ๐Ÿ”— Supported $ref Types + +readOnly/writeOnly resolution works with local and file reference types: + +| Reference Type | Example | Support | +|---------------|---------|---------| +| Local | `#/components/schemas/User` | โœ… Supported | +| File | `./common.yaml#/User` | โœ… Supported | + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: OpenAPI-only Options](cli-reference/openapi-only-options.md) - All OpenAPI-specific CLI options +- โš™๏ธ [CLI Reference: Base Options](cli-reference/base-options.md) - Input/output configuration options + +--- + +# Generate from JSON Schema + +Source: https://datamodel-code-generator.koxudaxi.dev/jsonschema/ + +Generate Pydantic models from JSON Schema definitions. See [Supported Data Types](./supported-data-types.md#openapi-3-and-json-schema) for supported JSON Schema features. + +## ๐Ÿš€ Quick Start + +```bash +datamodel-codegen --input person.json --input-file-type jsonschema --output model.py +``` + +## ๐Ÿ“ Example + +**person.json** +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "firstName": { + "type": "string", + "description": "The person's first name." + }, + "lastName": { + "type": "string", + "description": "The person's last name." + }, + "age": { + "description": "Age in years which must be equal to or greater than zero.", + "type": "integer", + "minimum": 0 + }, + "friends": { + "type": "array" + }, + "comment": { + "type": "null" + } + } +} +``` + + +**โœจ Generated model.py** +```python +# generated by datamodel-codegen: +# filename: person.json +# timestamp: 2020-04-27T16:12:27+00:00 + +from __future__ import annotations + +from typing import Any + +from pydantic import BaseModel, Field, conint + + +class Person(BaseModel): + firstName: str | None = Field(None, description="The person's first name.") + lastName: str | None = Field(None, description="The person's last name.") + age: conint(ge=0) | None = Field( + None, description='Age in years which must be equal to or greater than zero.' + ) + friends: list | None = None + comment: Any | None = None +``` + +## Tuple validation + +JSON Schema's [`prefixItems`](https://json-schema.org/understanding-json-schema/reference/array.html#tuple-validation) syntax lets you describe heterogeneous arrays. + +When: + +- `prefixItems` is present +- no `items` are specified +- `minItems`/`maxItems` match the number of prefix entries + +datamodel-code-generator emits precise tuple annotations. + +### Example + +```json +{ + "$defs": { + "Span": { + "type": "object", + "properties": { + "value": { "type": "integer" } + }, + "required": ["value"] + } + }, + "title": "defaults", + "type": "object", + "properties": { + "a": { + "type": "array", + "prefixItems": [ + { "$ref": "#/$defs/Span" }, + { "type": "string" } + ], + "minItems": 2, + "maxItems": 2 + } + }, + "required": ["a"] +} +``` + +```py +from pydantic import BaseModel + + +class Span(BaseModel): + value: int + + +class Defaults(BaseModel): + a: tuple[Span, str] +``` + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference](cli-reference/index.md) - Complete CLI options reference +- ๐Ÿ”ง [CLI Reference: Typing Customization](cli-reference/typing-customization.md) - Type annotation options +- ๐Ÿท๏ธ [CLI Reference: Field Customization](cli-reference/field-customization.md) - Field naming and constraint options +- ๐Ÿ“Š [Supported Data Types](supported-data-types.md) - JSON Schema data type support + +--- + +# Generate from JSON Data + +Source: https://datamodel-code-generator.koxudaxi.dev/jsondata/ + +Generate Pydantic models directly from JSON data. Under the hood, the generator uses [GenSON](https://pypi.org/project/genson/) to infer a JSON Schema from your input, then processes it the same way as [JSON Schema input](./jsonschema.md). + +## ๐Ÿš€ Quick Start + +```bash +datamodel-codegen --input pets.json --input-file-type json --output model.py +``` + +## ๐Ÿ“ Example + +**pets.json** +```json +{ + "pets": [ + { + "name": "dog", + "age": 2 + }, + { + "name": "cat", + "age": 1 + }, + { + "name": "snake", + "age": 3, + "nickname": "python" + } + ], + "status": 200 +} +``` + + +**โœจ Generated model.py** +```python +# generated by datamodel-codegen: +# filename: pets.json +# timestamp: 2020-04-27T16:08:21+00:00 + +from __future__ import annotations + +from pydantic import BaseModel + + +class Pet(BaseModel): + name: str + age: int + nickname: str | None = None + + +class Model(BaseModel): + pets: list[Pet] + status: int + +``` + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ“‹ [Generate from JSON Schema](jsonschema.md) - JSON Schema input documentation +- ๐Ÿ–ฅ๏ธ [CLI Reference](cli-reference/index.md) - Complete CLI options reference +- ๐Ÿ“Š [Supported Data Types](supported-data-types.md) - Data type support details + +--- + +# Generate from GraphQL + +Source: https://datamodel-code-generator.koxudaxi.dev/graphql/ + +Generate Pydantic models from GraphQL schema definitions. + +## ๐Ÿš€ Quick Start + +```bash +datamodel-codegen --input schema.graphql --input-file-type graphql --output model.py +``` + +!!! note "๐Ÿ“ฆ Installation" + GraphQL support requires the `graphql` extra: + ```bash + pip install 'datamodel-code-generator[graphql]' + ``` + +## ๐Ÿ“ Simple Example + +Let's consider a simple GraphQL schema (more details in [GraphQL Schemas and Types](https://graphql.org/learn/schema/)). + +**schema.graphql** +```graphql +type Book { + id: ID! + title: String + author: Author +} + +type Author { + id: ID! + name: String + books: [Book] +} + +input BooksInput { + ids: [ID!]! +} + +input AuthorBooksInput { + id: ID! +} + +type Query { + getBooks(input: BooksInput): [Book] + getAuthorBooks(input: AuthorBooksInput): [Book] +} +``` + +**โœจ Generated model.py** +```python +# generated by datamodel-codegen: +# filename: schema.graphql +# timestamp: 2023-11-20T17:04:42+00:00 + +from __future__ import annotations + +from typing import TypeAlias + +from pydantic import BaseModel, Field +from typing_extensions import Literal + +# The `Boolean` scalar type represents `true` or `false`. +Boolean: TypeAlias = bool + + +# 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. +ID: 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. +String: TypeAlias = str + + +class Author(BaseModel): + books: list[Book | None] | None = Field(default_factory=list) + id: ID + name: String | None = None + typename__: Literal['Author'] | None = Field('Author', alias='__typename') + + +class Book(BaseModel): + author: Author | None = None + id: ID + title: String | None = None + typename__: Literal['Book'] | None = Field('Book', alias='__typename') + + +class AuthorBooksInput(BaseModel): + id: ID + typename__: Literal['AuthorBooksInput'] | None = Field( + 'AuthorBooksInput', alias='__typename' + ) + + +class BooksInput(BaseModel): + ids: list[ID] + typename__: Literal['BooksInput'] | None = Field( + 'BooksInput', alias='__typename' + ) + +``` + +--- + +## ๐Ÿ“ค Response Deserialization + +For the following response of `getAuthorBooks` GraphQL query: + +**response.json** +```json +{ + "getAuthorBooks": [ + { + "author": { + "id": "51341cdscwef14r13", + "name": "J. K. Rowling" + }, + "id": "1321dfvrt211wdw", + "title": "Harry Potter and the Prisoner of Azkaban" + }, + { + "author": { + "id": "51341cdscwef14r13", + "name": "J. K. Rowling" + }, + "id": "dvsmu12e19xmqacqw9", + "title": "Fantastic Beasts: The Crimes of Grindelwald" + } + ] +} +``` + +**main.py** +```python +from model import Book + +response = {...} + +books = [ + Book.parse_obj(book_raw) for book_raw in response["getAuthorBooks"] +] +print(books) +# [Book(author=Author(books=[], id='51341cdscwef14r13', name='J. K. Rowling', typename__='Author'), id='1321dfvrt211wdw', title='Harry Potter and the Prisoner of Azkaban', typename__='Book'), Book(author=Author(books=[], id='51341cdscwef14r13', name='J. K. Rowling', typename__='Author'), id='dvsmu12e19xmqacqw9', title='Fantastic Beasts: The Crimes of Grindelwald', typename__='Book')] +``` + +--- + +## ๐ŸŽจ Custom Scalar Types + +```bash +datamodel-codegen --input schema.graphql --input-file-type graphql --output model.py --extra-template-data data.json +``` + +**schema.graphql** +```graphql +scalar Long + +type A { + id: ID! + duration: Long! +} +``` + +**data.json** +```json +{ + "Long": { + "py_type": "int" + } +} +``` + +**โœจ Generated model.py** +```python +# generated by datamodel-codegen: +# filename: custom-scalar-types.graphql +# timestamp: 2019-07-26T00:00:00+00:00 + +from __future__ import annotations + +from typing import Optional, TypeAlias + +from pydantic import BaseModel, Field +from typing_extensions import Literal + +# The `Boolean` scalar type represents `true` or `false`. +Boolean: TypeAlias = bool + + +# 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. +ID: TypeAlias = str + + +Long: TypeAlias = int + + +# 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. +String: TypeAlias = str + + +class A(BaseModel): + duration: Long + id: ID + typename__: Optional[Literal['A']] = Field('A', alias='__typename') + +``` + +--- + +## ๐Ÿšซ Excluding __typename Field + +When using generated models for GraphQL mutations, the `__typename` field may cause issues +as GraphQL servers typically don't expect this field in input data. + +Use the `--graphql-no-typename` option to exclude this field: + +```bash +datamodel-codegen --input schema.graphql --input-file-type graphql --output model.py --graphql-no-typename +``` + +**Before (default):** +```python +class Book(BaseModel): + id: ID + title: String | None = None + typename__: Literal['Book'] | None = Field('Book', alias='__typename') +``` + +**After (with --graphql-no-typename):** +```python +class Book(BaseModel): + id: ID + title: String | None = None +``` + +!!! warning "Union Type Discrimination" + If your schema uses GraphQL union types and you rely on `__typename` for type + discrimination during deserialization, excluding this field may break that functionality. + Consider using this option only for input types or schemas without unions. + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference](cli-reference/index.md) - Complete CLI options reference +- ๐Ÿ”ง [CLI Reference: Typing Customization](cli-reference/typing-customization.md) - Type annotation options +- ๐ŸŽจ [CLI Reference: `--extra-template-data`](cli-reference/template-customization.md#extra-template-data) - Custom scalar type mappings + +--- + +# Generate from Python Models {#python-model} + +Source: https://datamodel-code-generator.koxudaxi.dev/python-model/ + +Generate code from existing Python types: Pydantic models, dataclasses, TypedDict, or dict schemas. This is useful for converting between model types or generating from programmatically-defined schemas. + +## ๐Ÿš€ Quick Start {#quick-start} + +```bash +datamodel-codegen --input-model ./mymodule.py:User --output model.py +``` + +## Format {#format} + +``` +--input-model : +``` + +Simply specify the **file path** and **object name** separated by `:`. + +### Example {#format-example} + +``` +myproject/ +โ”œโ”€โ”€ src/ +โ”‚ โ””โ”€โ”€ models/ +โ”‚ โ””โ”€โ”€ user.py # class User(BaseModel): ... +โ””โ”€โ”€ schemas.py # USER_SCHEMA = {...} +``` + +```bash +# From file path (recommended - easy to copy-paste) +datamodel-codegen --input-model src/models/user.py:User --output model.py +datamodel-codegen --input-model ./schemas.py:USER_SCHEMA --input-file-type jsonschema + +# Windows paths also work +datamodel-codegen --input-model src\models\user.py:User +``` + +!!! tip "Copy-paste friendly" + Just copy the file path from your editor or file explorer, add `:ClassName`, and you're done! + +### Module format (alternative) {#module-format} + +You can also use Python module notation with dots: + +```bash +datamodel-codegen --input-model src.models.user:User +datamodel-codegen --input-model schemas:USER_SCHEMA --input-file-type jsonschema +``` + +!!! note "Current directory is auto-added to `sys.path`" + No `PYTHONPATH` configuration needed. + +!!! tip "File and package name conflict" + If both `mymodule.py` and `mymodule/` directory exist, use `./` prefix: + ```bash + datamodel-codegen --input-model ./mymodule.py:Model + ``` + +--- + +## Supported Input Types {#supported-input-types} + +| Type | Description | Requires | +|------|-------------|----------| +| Pydantic BaseModel | Pydantic v2 models with `model_json_schema()` | Pydantic v2 | +| dataclass | Standard library `@dataclass` | Pydantic v2 (for TypeAdapter) | +| Pydantic dataclass | `@pydantic.dataclasses.dataclass` | Pydantic v2 | +| TypedDict | `typing.TypedDict` subclasses | Pydantic v2 (for TypeAdapter) | +| dict | Dict containing JSON Schema or OpenAPI spec | - | + +!!! note "Pydantic v2 Required" + All Python type inputs (except raw dict) require Pydantic v2 runtime to convert to JSON Schema. + +--- + +## ๐Ÿ“ Examples {#examples} + +### Pydantic BaseModel {#pydantic-basemodel} + +**mymodule.py** +```python +from pydantic import BaseModel + +class User(BaseModel): + name: str + age: int +``` + +```bash +datamodel-codegen --input-model ./mymodule.py:User --output model.py +``` + +**โœจ Generated model.py** +```python +from __future__ import annotations + +from pydantic import BaseModel + + +class User(BaseModel): + name: str + age: int +``` + +### Convert Pydantic to TypedDict {#convert-pydantic-to-typeddict} + +```bash +datamodel-codegen --input-model ./mymodule.py:User --output-model-type typing.TypedDict --output model.py +``` + +**โœจ Generated model.py** +```python +from __future__ import annotations + +from typing import TypedDict + + +class User(TypedDict): + name: str + age: int +``` + +### Standard dataclass {#dataclass} + +**mymodule.py** +```python +from dataclasses import dataclass + +@dataclass +class User: + name: str + age: int +``` + +```bash +datamodel-codegen --input-model ./mymodule.py:User --output model.py +``` + +### TypedDict {#typeddict} + +**mymodule.py** +```python +from typing import TypedDict + +class User(TypedDict): + name: str + age: int +``` + +```bash +datamodel-codegen --input-model ./mymodule.py:User --output model.py +``` + +### Dict Schema (JSON Schema) {#dict-jsonschema} + +**mymodule.py** +```python +USER_SCHEMA = { + "type": "object", + "properties": { + "name": {"type": "string"}, + "age": {"type": "integer"}, + }, + "required": ["name", "age"], +} +``` + +```bash +datamodel-codegen --input-model ./mymodule.py:USER_SCHEMA --input-file-type jsonschema --output model.py +``` + +!!! warning "Dict requires --input-file-type" + When using a dict schema, you must specify `--input-file-type` (e.g., `jsonschema`, `openapi`). + +### Dict Schema (OpenAPI) {#dict-openapi} + +**mymodule.py** +```python +OPENAPI_SPEC = { + "openapi": "3.0.0", + "info": {"title": "API", "version": "1.0.0"}, + "paths": {}, + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "age": {"type": "integer"}, + }, + } + } + }, +} +``` + +```bash +datamodel-codegen --input-model ./mymodule.py:OPENAPI_SPEC --input-file-type openapi --output model.py +``` + +--- + +## Custom Python Types with x-python-type {#x-python-type} + +When using `x-python-type` in JSON Schema (via `WithJsonSchema` in Pydantic), the generator automatically resolves and generates the required imports. + +### Automatic Import Resolution {#import-resolution} + +The generator supports many common Python types out of the box: + +| Module | Supported Types | +|--------|-----------------| +| `typing` | `Any`, `Union`, `Optional`, `Literal`, `Final`, `ClassVar`, `Annotated`, `TypeVar`, `TypeAlias`, `Never`, `NoReturn`, `Self`, `LiteralString`, `TypeGuard`, `Type` | +| `collections` | `defaultdict`, `OrderedDict`, `Counter`, `deque`, `ChainMap` | +| `collections.abc` | `Callable`, `Iterable`, `Iterator`, `Generator`, `Awaitable`, `Coroutine`, `AsyncIterable`, `AsyncIterator`, `AsyncGenerator`, `Mapping`, `MutableMapping`, `Sequence`, `MutableSequence`, `Set`, `MutableSet`, `Collection`, `Reversible` | +| `pathlib` | `Path`, `PurePath` | +| `decimal` | `Decimal` | +| `uuid` | `UUID` | +| `datetime` | `datetime`, `date`, `time`, `timedelta` | +| `enum` | `Enum`, `IntEnum`, `StrEnum`, `Flag`, `IntFlag` | +| `re` | `Pattern`, `Match` | + +For types not in this list, the generator dynamically searches common modules to resolve imports. + +### Example {#x-python-type-example} + +**mymodule.py** +```python +from collections import defaultdict +from typing import Any, Annotated +from pydantic import BaseModel, Field, WithJsonSchema + +class Config(BaseModel): + data: Annotated[ + defaultdict[str, Annotated[dict[str, Any], Field(default_factory=dict)]], + WithJsonSchema({'type': 'object', 'x-python-type': 'defaultdict[str, dict[str, Any]]'}) + ] | None = None +``` + +```bash +datamodel-codegen --input-model ./mymodule.py:Config --output-model-type typing.TypedDict +``` + +**โœจ Generated output** +```python +from __future__ import annotations + +from collections import defaultdict +from typing import Any, TypedDict + +from typing_extensions import NotRequired + + +class Config(TypedDict): + data: NotRequired[defaultdict[str, dict[str, Any]] | None] +``` + +!!! tip "Fully Qualified Paths" + You can also use fully qualified paths in `x-python-type` (e.g., `collections.defaultdict`), which are always resolved correctly regardless of the static mapping. + +--- + +## Mutual Exclusion {#mutual-exclusion} + +`--input-model` cannot be used with: + +- `--input` (file input) +- `--url` (URL input) +- `--watch` (file watching) + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference](cli-reference/index.md) - Complete CLI options reference +- ๐Ÿ“ [CLI Reference: Base Options](cli-reference/base-options.md#input-model) - `--input-model` option details +- ๐Ÿ“‹ [Generate from JSON Schema](jsonschema.md) - JSON Schema input documentation + +--- + +# Output Model Types + +Source: https://datamodel-code-generator.koxudaxi.dev/what_is_the_difference_between_v1_and_v2/ + + + +# Output Model Types + +datamodel-code-generator supports multiple output model types. This page compares them to help you choose the right one for your project. + +## Quick Comparison + +| Model Type | Validation | Serialization | Performance | Use Case | +|------------|------------|---------------|-------------|----------| +| **Pydantic v2** | Runtime | Built-in | Fast | New projects, APIs, data validation | +| **Pydantic v2 dataclass** | Runtime | Built-in | Fast | Pydantic validation with dataclass syntax | +| **Pydantic v1** | Runtime | Built-in | Moderate | Legacy compatibility | +| **dataclasses** | None | Manual | Fastest | Simple data containers, no validation needed | +| **TypedDict** | Static only | Dict-compatible | N/A | Type hints for dicts, JSON APIs | +| **msgspec** | Runtime | Built-in | Fastest | High-performance serialization | + +--- + +## Pydantic v2 (Recommended) + +**Use `--output-model-type pydantic_v2.BaseModel`** + +Pydantic v2 is recommended for new projects. It offers better performance and a modern API. + +```bash +datamodel-codegen --input schema.json --output-model-type pydantic_v2.BaseModel --output model.py +``` + +```python +from pydantic import BaseModel, Field, RootModel + +class Pet(BaseModel): + id: int = Field(..., ge=0) + name: str = Field(..., max_length=256) + tag: str | None = None + +class Pets(RootModel[list[Pet]]): + root: list[Pet] +``` + +### When to use + +- New projects without Pydantic v1 dependencies +- APIs requiring data validation +- Projects needing JSON Schema generation from models + +--- + +## Pydantic v2 dataclass + +**Use `--output-model-type pydantic_v2.dataclass`** + +Pydantic v2 dataclass combines the familiar dataclass syntax with Pydantic's validation capabilities. + +```bash +datamodel-codegen --input schema.json --output-model-type pydantic_v2.dataclass --output model.py +``` + +```python +from pydantic.dataclasses import dataclass +from typing import Optional + +@dataclass +class Pet: + id: int + name: str + tag: Optional[str] = None +``` + +### When to use + +- Want to use dataclass syntax with Pydantic validation +- Migrating from dataclasses but need validation +- Prefer decorator-based class definition + +--- + +## Pydantic v1 + +**Use `--output-model-type pydantic.BaseModel`** (default) + +Pydantic v1 is the default for backward compatibility with existing codebases. + +```bash +datamodel-codegen --input schema.json --output-model-type pydantic.BaseModel --output model.py +``` + +```python +from pydantic import BaseModel, Field + +class Pet(BaseModel): + id: int = Field(..., ge=0) + name: str = Field(..., max_length=256) + tag: Optional[str] = None + +class Pets(BaseModel): + __root__: List[Pet] +``` + +### Migration from v1 to v2 + +Key differences when migrating: + +| v1 | v2 | Notes | +|----|----|----| +| `__root__` | `RootModel` | Custom root types now use `RootModel` class | +| `const` | Removed | Use `Literal` types instead | +| `min_items` | `min_length` | | +| `max_items` | `max_length` | | +| `unique_items` | Removed | List replaced by `set` type | +| `allow_mutation` | `frozen` | Inverse value | +| `regex` | `pattern` | | +| `pydantic.Config` | `pydantic.ConfigDict` | | + +See [Pydantic v2 Migration Guide](https://docs.pydantic.dev/2.0/migration/) for details. + +--- + +## dataclasses + +**Use `--output-model-type dataclasses.dataclass`** + +Python's built-in dataclasses for simple data containers without runtime validation. + +```bash +datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass --output model.py +``` + +```python +from dataclasses import dataclass +from typing import Optional + +@dataclass +class Pet: + id: int + name: str + tag: Optional[str] = None +``` + +### Options for dataclasses + +| Option | Description | +|--------|-------------| +| `--frozen-dataclasses` | Generate immutable dataclasses (`frozen=True`) | +| `--keyword-only` | Require keyword arguments (`kw_only=True`, Python 3.10+) | +| `--dataclass-arguments` | Custom decorator arguments as JSON | + +```bash +# Frozen, keyword-only dataclasses +datamodel-codegen --input schema.json --output-model-type dataclasses.dataclass \ + --frozen-dataclasses --keyword-only --target-python-version 3.10 +``` + +### When to use + +- Simple data structures without validation needs +- Performance-critical code where validation overhead matters +- Interoperability with code expecting dataclasses + +--- + +## TypedDict + +**Use `--output-model-type typing.TypedDict`** + +TypedDict provides static type checking for dictionary structures. + +```bash +datamodel-codegen --input schema.json --output-model-type typing.TypedDict --output model.py +``` + +```python +from typing import TypedDict, NotRequired + +class Pet(TypedDict): + id: int + name: str + tag: NotRequired[str] +``` + +### When to use + +- Working with JSON APIs where data remains as dicts +- Static type checking without runtime overhead +- Gradual typing of existing dict-based code + +--- + +## msgspec + +**Use `--output-model-type msgspec.Struct`** + +[msgspec](https://github.com/jcrist/msgspec) offers high-performance serialization with validation. + +```bash +pip install 'datamodel-code-generator[msgspec]' +datamodel-codegen --input schema.json --output-model-type msgspec.Struct --output model.py +``` + +```python +from msgspec import Struct, field +from typing import Union, UnsetType +from msgspec import UNSET + +class Pet(Struct): + id: int + name: str + tag: Union[str, UnsetType] = UNSET +``` + +### When to use + +- High-performance JSON/MessagePack serialization +- Memory-efficient data structures +- APIs with strict performance requirements + +--- + +## Choosing the Right Type + +```mermaid +graph TD + A[Need runtime validation?] -->|Yes| B[Need best performance?] + A -->|No| C[Need type hints for dicts?] + B -->|Yes| D[msgspec.Struct] + B -->|No| E[Pydantic v1 dependency?] + E -->|Yes| F[pydantic.BaseModel] + E -->|No| G[Prefer dataclass syntax?] + G -->|Yes| H[pydantic_v2.dataclass] + G -->|No| I[pydantic_v2.BaseModel] + C -->|Yes| J[typing.TypedDict] + C -->|No| K[dataclasses.dataclass] +``` + +### Decision Guide + +1. **API with validation** โ†’ Pydantic v2 +2. **Validation with dataclass syntax** โ†’ Pydantic v2 dataclass +3. **Legacy Pydantic v1 project** โ†’ Pydantic v1 +4. **High-performance serialization** โ†’ msgspec +5. **Simple data containers** โ†’ dataclasses +6. **Dict-based JSON handling** โ†’ TypedDict + +--- + +## See Also + +- [CLI Reference: `--output-model-type`](cli-reference/model-customization.md#output-model-type) +- [CLI Reference: Model Customization](cli-reference/model-customization.md) +- [Pydantic Documentation](https://docs.pydantic.dev/) +- [msgspec Documentation](https://jcristharif.com/msgspec/) + +--- + +# Model Reuse and Deduplication + +Source: https://datamodel-code-generator.koxudaxi.dev/model-reuse/ + + + +# Model Reuse and Deduplication + +When generating models from schemas, you may encounter duplicate model definitions. datamodel-code-generator provides options to deduplicate models and share them across multiple files, improving output structure, reducing diff sizes, and enhancing performance. + +## Quick Overview + +| Option | Description | +|--------|-------------| +| `--reuse-model` | Deduplicate identical model/enum definitions | +| `--reuse-scope` | Control scope of deduplication (`root` or `tree`) | +| `--shared-module-name` | Name for shared module in multi-file output | +| `--collapse-root-models` | Inline root models instead of creating wrappers | +| `--use-type-alias` | Create TypeAlias for reusable field types (see [Reducing Duplicate Field Types](#reducing-duplicate-field-types)) | + +--- + +## `--reuse-model` + +The `--reuse-model` flag detects identical enum or model definitions and generates a single shared definition instead of duplicates. + +### Without `--reuse-model` + +```bash +datamodel-codegen --input schema.json --output model.py +``` + +```python +# Duplicate enums for animal and pet fields +class Animal(Enum): + dog = 'dog' + cat = 'cat' + +class Pet(Enum): # Duplicate! + dog = 'dog' + cat = 'cat' + +class User(BaseModel): + animal: Optional[Animal] = None + pet: Optional[Pet] = None +``` + +### With `--reuse-model` + +```bash +datamodel-codegen --input schema.json --output model.py --reuse-model +``` + +```python +# Single shared enum +class Animal(Enum): + dog = 'dog' + cat = 'cat' + +class User(BaseModel): + animal: Optional[Animal] = None + pet: Optional[Animal] = None # Reuses Animal +``` + +### Benefits + +- **Smaller output** - Less generated code +- **Cleaner diffs** - Changes to shared types only appear once +- **Better performance** - Faster generation for large schemas +- **Type consistency** - Same types are truly the same + +--- + +## `--reuse-scope` + +Controls the scope for model reuse detection when processing multiple input files. + +| Value | Description | +|-------|-------------| +| `root` | Detect duplicates only within each input file (default) | +| `tree` | Detect duplicates across all input files | + +### Single-file input + +For single-file input, `--reuse-scope` has no effect. Use `--reuse-model` alone. + +### Multi-file input with `tree` scope + +When generating from multiple schema files to a directory: + +```bash +datamodel-codegen --input schemas/ --output models/ --reuse-model --reuse-scope tree +``` + +**Input files:** +```text +schemas/ +โ”œโ”€โ”€ user.json # defines SharedModel +โ””โ”€โ”€ order.json # also defines identical SharedModel +``` + +**Output with `--reuse-scope tree`:** +```text +models/ +โ”œโ”€โ”€ __init__.py +โ”œโ”€โ”€ user.py # imports from shared +โ”œโ”€โ”€ order.py # imports from shared +โ””โ”€โ”€ shared.py # SharedModel defined once +``` + +```python +# models/user.py +from .shared import SharedModel + +class User(BaseModel): + data: Optional[SharedModel] = None + +# models/shared.py +class SharedModel(BaseModel): + id: Optional[int] = None + name: Optional[str] = None +``` + +--- + +## `--shared-module-name` + +Customize the name of the shared module when using `--reuse-scope tree`. + +```bash +datamodel-codegen --input schemas/ --output models/ \ + --reuse-model --reuse-scope tree --shared-module-name common +``` + +**Output:** +```text +models/ +โ”œโ”€โ”€ __init__.py +โ”œโ”€โ”€ user.py +โ”œโ”€โ”€ order.py +โ””โ”€โ”€ common.py # Instead of shared.py +``` + +--- + +## `--collapse-root-models` + +Inline root model definitions instead of creating separate wrapper classes. + +### Without `--collapse-root-models` + +```python +class UserId(BaseModel): + __root__: str + +class User(BaseModel): + id: UserId +``` + +### With `--collapse-root-models` + +```python +class User(BaseModel): + id: str # Inlined +``` + +### When to use + +- Simpler output when wrapper classes aren't needed +- Reducing the number of generated classes +- When root models are just type aliases + +--- + +## Combining Options + +### Recommended for large multi-file projects + +```bash +datamodel-codegen \ + --input schemas/ \ + --output models/ \ + --reuse-model \ + --reuse-scope tree \ + --shared-module-name common \ + --collapse-root-models +``` + +This produces: +- Deduplicated models across all files +- Shared types in a `common.py` module +- Inlined simple root models +- Minimal, clean output + +### Recommended for single-file projects + +```bash +datamodel-codegen \ + --input schema.json \ + --output model.py \ + --reuse-model \ + --collapse-root-models +``` + +--- + +## Performance Impact + +For large schemas with many models: + +| Scenario | Without reuse | With reuse | +|----------|---------------|------------| +| 100 schemas, 50% duplicates | 100 models | ~50 models | +| Generation time | Baseline | Faster (less to generate) | +| Output size | Large | Smaller | +| Git diff on type change | Multiple files | Single location | + +!!! tip "Performance tip" + For very large schemas, combine `--reuse-model` with `--disable-warnings` to speed up generation: + + ```bash + datamodel-codegen --reuse-model --disable-warnings --input large-schema.json + ``` + +--- + +## Output Structure Comparison + +### Without deduplication + +```text +models/ +โ”œโ”€โ”€ user.py # UserStatus enum +โ”œโ”€โ”€ order.py # OrderStatus enum (duplicate of UserStatus!) +โ””โ”€โ”€ product.py # ProductStatus enum (duplicate!) +``` + +### With `--reuse-model --reuse-scope tree` + +```text +models/ +โ”œโ”€โ”€ __init__.py +โ”œโ”€โ”€ user.py # imports Status from shared +โ”œโ”€โ”€ order.py # imports Status from shared +โ”œโ”€โ”€ product.py # imports Status from shared +โ””โ”€โ”€ shared.py # Status enum defined once +``` + +--- + +## Reducing Duplicate Field Types + +When multiple classes share the same field type with identical constraints or metadata, you can reduce duplication by defining the type once in `$defs` and referencing it with `$ref`. Combined with `--use-type-alias`, this creates a single TypeAlias that's reused across all classes. + +### Problem: Duplicate Annotated Fields + +Without using `$ref`, each class gets its own inline field definition: + +```python +class ClassA(BaseModel): + place_name: Annotated[str, Field(alias='placeName')] # Duplicate! + +class ClassB(BaseModel): + place_name: Annotated[str, Field(alias='placeName')] # Duplicate! +``` + +### Solution: Use `$defs` with `--use-type-alias` + +**Step 1: Define the shared type in `$defs`** + +```json +{ + "$defs": { + "PlaceName": { + "type": "string", + "title": "PlaceName", + "description": "A place name" + }, + "ClassA": { + "type": "object", + "properties": { + "place_name": { "$ref": "#/$defs/PlaceName" } + } + }, + "ClassB": { + "type": "object", + "properties": { + "place_name": { "$ref": "#/$defs/PlaceName" } + } + } + } +} +``` + +**Step 2: Generate with `--use-type-alias`** + +```bash +datamodel-codegen \ + --input schema.json \ + --output model.py \ + --use-type-alias +``` + +### Result: Single TypeAlias reused across classes + +```python +PlaceName = TypeAliasType( + "PlaceName", + Annotated[str, Field(..., description='A place name', title='PlaceName')], +) + + +class ClassA(BaseModel): + place_name: PlaceName # Reuses the TypeAlias + + +class ClassB(BaseModel): + place_name: PlaceName # Reuses the TypeAlias +``` + +### Benefits + +- **Single source of truth** - Field type is defined once +- **Easier maintenance** - Change the type in one place +- **Cleaner generated code** - No redundant annotations +- **Type safety** - All fields share the exact same type + +### When to Use This Pattern + +This pattern is ideal when: + +- Multiple classes share fields with the same constraints (e.g., `minLength`, `pattern`) +- Fields have identical metadata (e.g., `description`, `examples`) +- You want to ensure type consistency across your schema + +--- + +## See Also + +- [CLI Reference: `--reuse-model`](cli-reference/model-customization.md#reuse-model) +- [CLI Reference: `--reuse-scope`](cli-reference/model-customization.md#reuse-scope) +- [CLI Reference: `--collapse-root-models`](cli-reference/model-customization.md#collapse-root-models) +- [CLI Reference: `--use-type-alias`](cli-reference/typing-customization.md#use-type-alias) +- [Root Models and Type Aliases](root-model-and-type-alias.md) +- [FAQ: Performance](faq.md#-performance) + +--- + +# Module Structure and Exports + +Source: https://datamodel-code-generator.koxudaxi.dev/module-exports/ + + + +# Module Structure and Exports + +When generating models to a directory structure, datamodel-code-generator can automatically create `__init__.py` files with `__all__` exports. This page explains how to control this behavior. + +## Quick Overview + +| Option | Description | +|--------|-------------| +| `--all-exports-scope` | Control which modules get `__all__` exports | +| `--all-exports-collision-strategy` | Handle name collisions in recursive exports | +| `--treat-dot-as-module` | Convert dots in names to nested modules | + +--- + +## `--all-exports-scope` + +Controls the scope of `__all__` generation in `__init__.py` files. + +| Value | Description | +|-------|-------------| +| `none` | No `__all__` generation (default) | +| `local` | Export only the module's own definitions | +| `recursive` | Export all definitions from child modules | + +### Example: `none` (default) + +```bash +datamodel-codegen --input schemas/ --output models/ +``` + +```python +# models/__init__.py +# (empty or minimal imports) +``` + +### Example: `local` + +```bash +datamodel-codegen --input schemas/ --output models/ --all-exports-scope local +``` + +```python +# models/__init__.py +from .user import User +from .order import Order + +__all__ = ["User", "Order"] +``` + +### Example: `recursive` + +```bash +datamodel-codegen --input schemas/ --output models/ --all-exports-scope recursive +``` + +```python +# models/__init__.py +from .user import User +from .order import Order +from .common.status import Status +from .common.types import ID, Timestamp + +__all__ = ["User", "Order", "Status", "ID", "Timestamp"] +``` + +--- + +## `--all-exports-collision-strategy` + +When using `--all-exports-scope recursive`, name collisions can occur if multiple modules define the same class name. This option controls how to handle them. + +| Value | Description | +|-------|-------------| +| `minimal-prefix` | Add minimum module path prefix to disambiguate | +| `full-prefix` | Use complete module path for all exports | + +### The Problem + +```text +models/ +โ”œโ”€โ”€ user/ +โ”‚ โ””โ”€โ”€ types.py # defines `ID` +โ””โ”€โ”€ order/ + โ””โ”€โ”€ types.py # also defines `ID` +``` + +Both modules define `ID`, causing a collision when exporting recursively. + +### Solution: `minimal-prefix` + +```bash +datamodel-codegen --input schemas/ --output models/ \ + --all-exports-scope recursive \ + --all-exports-collision-strategy minimal-prefix +``` + +```python +# models/__init__.py +from .user.types import ID as user_ID +from .order.types import ID as order_ID + +__all__ = ["user_ID", "order_ID"] +``` + +Only colliding names get prefixed. + +### Solution: `full-prefix` + +```bash +datamodel-codegen --input schemas/ --output models/ \ + --all-exports-scope recursive \ + --all-exports-collision-strategy full-prefix +``` + +```python +# models/__init__.py +from .user.types import ID as user_types_ID +from .order.types import ID as order_types_ID + +__all__ = ["user_types_ID", "order_types_ID"] +``` + +All names use the full module path prefix. + +--- + +## `--treat-dot-as-module` + +Converts dots in schema names to nested module directories. + +### Without `--treat-dot-as-module` + +Schema with `title: "api.v1.User"` generates: + +```python +# models.py +class ApiV1User(BaseModel): + ... +``` + +### With `--treat-dot-as-module` + +```bash +datamodel-codegen --input schema.json --output models/ --treat-dot-as-module +``` + +Schema with `title: "api.v1.User"` generates: + +```text +models/ +โ”œโ”€โ”€ __init__.py +โ””โ”€โ”€ api/ + โ”œโ”€โ”€ __init__.py + โ””โ”€โ”€ v1/ + โ”œโ”€โ”€ __init__.py + โ””โ”€โ”€ user.py # contains class User +``` + +This is useful for: +- Organizing large schemas by namespace +- Mirroring API versioning structure +- Keeping related models together + +--- + +## Common Patterns + +### Pattern 1: Flat output with local exports + +Best for small to medium projects with a single output file or simple structure. + +```bash +datamodel-codegen --input schema.yaml --output models/ --all-exports-scope local +``` + +### Pattern 2: Hierarchical with recursive exports + +Best for large projects with many schemas organized by domain. + +```bash +datamodel-codegen --input schemas/ --output models/ \ + --all-exports-scope recursive \ + --all-exports-collision-strategy minimal-prefix \ + --treat-dot-as-module +``` + +### Pattern 3: OpenAPI with module structure + +Best for OpenAPI schemas with versioned endpoints. + +```bash +datamodel-codegen --input openapi.yaml --output models/ \ + --treat-dot-as-module \ + --all-exports-scope recursive +``` + +--- + +## Troubleshooting + +### Import errors after generation + +If you see `ImportError: cannot import name 'X'`: + +1. Check if `__all__` is generated correctly +2. Verify the module structure matches your imports +3. Try `--all-exports-scope local` first, then `recursive` + +### Name collisions + +If you see duplicate class names: + +1. Use `--all-exports-collision-strategy minimal-prefix` +2. Or use `--all-exports-collision-strategy full-prefix` for maximum clarity +3. Consider restructuring your schemas to avoid collisions + +### Circular imports + +If you encounter circular import errors: + +1. Check the generated `__init__.py` files +2. Consider using `--all-exports-scope local` instead of `recursive` +3. Use lazy imports in your application code + +--- + +## See Also + +- [CLI Reference: `--all-exports-scope`](cli-reference/general-options.md#all-exports-scope) +- [CLI Reference: `--all-exports-collision-strategy`](cli-reference/general-options.md#all-exports-collision-strategy) +- [CLI Reference: `--treat-dot-as-module`](cli-reference/template-customization.md#treat-dot-as-module) +- [Model Reuse and Deduplication](model-reuse.md) + +--- + +# Type Mappings and Custom Types + +Source: https://datamodel-code-generator.koxudaxi.dev/type-mappings/ + + + +# Type Mappings and Custom Types + +datamodel-code-generator allows you to customize how schema types are mapped to Python types. This is essential for projects with specific type requirements, datetime handling preferences, or third-party library integrations. + +## Quick Overview + +| Option | Description | +|--------|-------------| +| `--type-mappings` | Map schema types to custom Python types | +| `--strict-types` | Use Pydantic strict types for validation | +| `--output-datetime-class` | Choose datetime output type | +| `--use-pendulum` | Use Pendulum library for datetime types | +| `--use-decimal-for-multiple-of` | Use Decimal for multipleOf constraints | +| `format: "email"` | Email validation (requires `email-validator`) | +| `format: "ulid"` | ULID type support (requires `python-ulid`) | + +--- + +## `--type-mappings` + +Maps schema type+format combinations to other format names. This allows you to override how specific formats are interpreted. + +### Format + +```bash +--type-mappings = [= ...] +``` + +### Basic Examples + +```bash +# Map binary format to string (generates str instead of bytes) +datamodel-codegen --input schema.json --output models.py \ + --type-mappings "binary=string" + +# Map email format to string (generates str instead of EmailStr) +datamodel-codegen --input schema.json --output models.py \ + --type-mappings "string+email=string" + +# Multiple mappings +datamodel-codegen --input schema.json --output models.py \ + --type-mappings "string+email=string" "string+uuid=string" +``` + +### Mapping Syntax + +| Syntax | Description | Example | +|--------|-------------|---------| +| `format=target` | Map format (assumes string type) | `binary=string` | +| `type+format=target` | Map type with format | `string+email=string` | + +### Avoiding Pydantic Optional Extras + +Some Pydantic types require optional dependencies. Use `--type-mappings` to generate plain types instead: + +```bash +# Avoid pydantic[email] dependency (EmailStr requires email-validator) +--type-mappings "string+email=string" "string+idn-email=string" + +# Generate str instead of UUID for uuid format +--type-mappings "string+uuid=string" +``` + +### Available Target Formats + +| Target | Generated Type | +|--------|----------------| +| `string` | `str` | +| `integer` | `int` | +| `number` | `float` | +| `boolean` | `bool` | +| `binary` | `bytes` | +| `date` | `datetime.date` | +| `date-time` | `datetime.datetime` | +| `uuid` | `UUID` | +| `email` | `EmailStr` | +| `uri` | `AnyUrl` | + +### pyproject.toml Configuration + +```toml +[tool.datamodel-codegen] +type-mappings = [ + "string+email=string", + "string+idn-email=string", + "binary=string", +] +``` + +--- + +## `--strict-types` + +Generates Pydantic strict types that don't perform type coercion during validation. + +### Available Strict Types + +| Value | Strict Type | Rejects | +|-------|-------------|---------| +| `str` | `StrictStr` | Integers, floats | +| `int` | `StrictInt` | Strings, floats | +| `float` | `StrictFloat` | Strings, integers | +| `bool` | `StrictBool` | Strings, integers | +| `bytes` | `StrictBytes` | Strings | + +### Without `--strict-types` + +```python +class User(BaseModel): + id: int # Accepts "123" and converts to 123 + name: str # Accepts 123 and converts to "123" + active: bool # Accepts 1 and converts to True +``` + +### With `--strict-types` + +```bash +datamodel-codegen --input schema.json --output models.py \ + --strict-types str int bool +``` + +```python +from pydantic import StrictBool, StrictInt, StrictStr + +class User(BaseModel): + id: StrictInt # Rejects "123", requires integer + name: StrictStr # Rejects 123, requires string + active: StrictBool # Rejects 1, requires boolean +``` + +### When to use + +- API validation where type coercion is undesirable +- Data pipelines requiring exact types +- Security-sensitive applications +- Testing environments requiring strict type checking + +--- + +## `--output-datetime-class` + +Controls the Python type used for `date-time` formatted strings. + +| Value | Output Type | Description | +|-------|-------------|-------------| +| `datetime` | `datetime.datetime` | Standard library datetime (default) | +| `AwareDatetime` | `pydantic.AwareDatetime` | Requires timezone info | +| `NaiveDatetime` | `pydantic.NaiveDatetime` | Rejects timezone info | + +### Default behavior + +```python +from datetime import datetime + +class Event(BaseModel): + created_at: datetime # Accepts both aware and naive +``` + +### AwareDatetime (recommended for APIs) + +```bash +datamodel-codegen --input schema.json --output models.py \ + --output-datetime-class AwareDatetime +``` + +```python +from pydantic import AwareDatetime + +class Event(BaseModel): + created_at: AwareDatetime # Requires timezone, e.g., 2024-01-01T00:00:00Z +``` + +### NaiveDatetime + +```bash +datamodel-codegen --input schema.json --output models.py \ + --output-datetime-class NaiveDatetime +``` + +```python +from pydantic import NaiveDatetime + +class Event(BaseModel): + created_at: NaiveDatetime # Rejects timezone, e.g., 2024-01-01T00:00:00 +``` + +### When to use each + +| Use Case | Recommended Class | +|----------|-------------------| +| REST APIs | `AwareDatetime` | +| Database models | `datetime` or `NaiveDatetime` | +| Logs with UTC timestamps | `AwareDatetime` | +| Local time applications | `NaiveDatetime` | + +--- + +## `--use-pendulum` + +Uses [Pendulum](https://pendulum.eustace.io/) library types instead of standard library datetime. + +```bash +pip install pendulum +datamodel-codegen --input schema.json --output models.py --use-pendulum +``` + +### Output + +```python +import pendulum + +class Event(BaseModel): + created_at: pendulum.DateTime + date: pendulum.Date + time: pendulum.Time +``` + +### Benefits of Pendulum + +- Timezone handling is simpler and more intuitive +- Human-friendly datetime manipulation +- Better serialization defaults +- Immutable by default + +### When to use + +- Projects already using Pendulum +- Applications requiring complex datetime manipulation +- When timezone handling is a priority + +--- + +## Email Format Support + +The generator supports the `email` and `idn-email` string formats, which generate Pydantic's `EmailStr` type. + +!!! warning "Required Dependency" + The `email` format requires the `email-validator` package to be installed: + ```bash + pip install email-validator + ``` + Or install Pydantic with the email extra: + ```bash + pip install pydantic[email] + ``` + +### Schema Example + +```json +{ + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email" + } + } +} +``` + +### Output + +```python +from pydantic import BaseModel, EmailStr + +class MyModel(BaseModel): + email: EmailStr +``` + +### Avoiding the Dependency + +If you don't want to install `email-validator`, you can map email formats to plain strings: + +```bash +datamodel-codegen --input schema.json --output models.py \ + --type-mappings "string+email=string" "string+idn-email=string" +``` + +This generates `str` instead of `EmailStr`. + +--- + +## ULID Format Support + +The generator supports the `ulid` string format, which generates [`python-ulid`](https://github.com/mdomke/python-ulid) types. + +!!! warning "Required Dependency" + The `ulid` format requires the `python-ulid` package to be installed: + ```bash + pip install python-ulid + ``` + For Pydantic integration, use: + ```bash + pip install python-ulid[pydantic] + ``` + +### Schema Example + +```json +{ + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "ulid" + } + } +} +``` + +### Output + +```python +from ulid import ULID +from pydantic import BaseModel + +class MyModel(BaseModel): + id: ULID +``` + +### What is ULID? + +ULID (Universally Unique Lexicographically Sortable Identifier) is an alternative to UUID that offers: + +- **Lexicographic sorting** - ULIDs sort naturally by creation time +- **Compactness** - 26 characters vs 36 for UUID +- **URL-safe** - Uses Crockford's Base32 encoding +- **Timestamp encoded** - First 10 characters encode creation time + +### When to use + +- Distributed systems requiring time-ordered IDs +- Applications where database index performance matters +- When you need both uniqueness and sortability + +--- + +## `--use-decimal-for-multiple-of` + +Uses `Decimal` type for numbers with `multipleOf` constraints to avoid floating-point precision issues. + +### The Problem + +```yaml +properties: + price: + type: number + multipleOf: 0.01 # Currency precision +``` + +Without this option, floating-point arithmetic can cause validation issues: + +```python +# 0.1 + 0.2 = 0.30000000000000004 in floating-point +price = 0.30000000000000004 # May fail multipleOf validation +``` + +### Solution + +```bash +datamodel-codegen --input schema.json --output models.py \ + --use-decimal-for-multiple-of +``` + +```python +from decimal import Decimal + +class Product(BaseModel): + price: Decimal # Exact decimal arithmetic +``` + +### When to use + +- Financial applications +- Scientific calculations requiring precision +- Any schema with `multipleOf` constraints + +--- + +## Common Patterns + +### Pattern 1: Minimal dependencies + +Avoid optional Pydantic dependencies by mapping special formats to plain types: + +```bash +datamodel-codegen --input schema.json --output models.py \ + --type-mappings "string+email=string" "string+idn-email=string" +``` + +### Pattern 2: Strict API validation + +```bash +datamodel-codegen --input schema.json --output models.py \ + --strict-types str int float bool \ + --output-datetime-class AwareDatetime \ + --field-constraints +``` + +### Pattern 3: Financial application + +```bash +datamodel-codegen --input schema.json --output models.py \ + --use-decimal-for-multiple-of \ + --strict-types str int +``` + +### Pattern 4: Pendulum datetime handling + +```bash +datamodel-codegen --input schema.json --output models.py \ + --use-pendulum \ + --strict-types str int +``` + +--- + +## Type Mapping Reference + +### Common Format Mappings + +| Schema Format | Default Type | With `--type-mappings "format=string"` | +|---------------|--------------|----------------------------------------| +| `email` | `EmailStr` | `str` | +| `idn-email` | `EmailStr` | `str` | +| `uuid` | `UUID` | `str` | +| `ulid` | `ULID` (requires `python-ulid`) | `str` | +| `uri` | `AnyUrl` | `str` | +| `binary` | `bytes` | `str` | + +!!! note "Other type customization options" + For datetime types, use `--output-datetime-class` or `--use-pendulum` instead of `--type-mappings`. + +--- + +## See Also + +- [CLI Reference: `--type-mappings`](cli-reference/typing-customization.md#type-mappings) +- [CLI Reference: `--strict-types`](cli-reference/typing-customization.md#strict-types) +- [CLI Reference: `--output-datetime-class`](cli-reference/typing-customization.md#output-datetime-class) +- [CLI Reference: `--use-pendulum`](cli-reference/typing-customization.md#use-pendulum) +- [Field Constraints](field-constraints.md) +- [Python Version Compatibility](python-version-compatibility.md) + +--- + +# Python Version Compatibility + +Source: https://datamodel-code-generator.koxudaxi.dev/python-version-compatibility/ + + + +# Python Version Compatibility + +datamodel-code-generator can generate code compatible with different Python versions. This page explains how to control type annotation syntax and imports for your target environment. + +## Quick Overview + +| Option | Description | +|--------|-------------| +| `--target-python-version` | Set the minimum Python version for generated code | +| `--use-union-operator` | Use `X \| Y` instead of `Union[X, Y]` | +| `--use-standard-collections` | Use `list`, `dict` instead of `List`, `Dict` | +| `--use-annotated` | Use `Annotated` for field metadata | +| `--use-generic-container-types` | Use `Sequence`, `Mapping` instead of `list`, `dict` | +| `--disable-future-imports` | Don't add `from __future__ import annotations` | + +--- + +## `--target-python-version` + +Sets the minimum Python version for the generated code. This automatically adjusts type annotation syntax. + +| Version | Union Syntax | Collection Syntax | Notes | +|---------|--------------|-------------------|-------| +| 3.10 | `X \| Y` | `list[T]`, `dict[K, V]` | Union operator available | +| 3.11 | `X \| Y` | `list[T]`, `dict[K, V]` | `Self` type available | +| 3.12+ | `X \| Y` | `list[T]`, `dict[K, V]` | `type` statement available | + +### Example: Python 3.10+ + +```bash +datamodel-codegen --input schema.json --output models.py \ + --target-python-version 3.10 +``` + +```python +class User(BaseModel): + id: int + tags: list[str] + metadata: str | int | None = None +``` + +--- + +## `--use-union-operator` + +Uses the `|` operator for union types instead of `Union[X, Y]`. + +### Without `--use-union-operator` + +```python +from typing import Union, Optional + +class Item(BaseModel): + value: Union[str, int] + label: Optional[str] = None # Same as Union[str, None] +``` + +### With `--use-union-operator` + +```bash +datamodel-codegen --input schema.json --output models.py --use-union-operator +``` + +```python +class Item(BaseModel): + value: str | int + label: str | None = None +``` + +### Compatibility Note + +The union operator `|` requires: +- Python 3.10+ at runtime, OR +- `from __future__ import annotations` (Python 3.7+) for postponed evaluation + +--- + +## `--use-standard-collections` + +Uses built-in collection types instead of `typing` module generics. + +### Without `--use-standard-collections` + +```python +from typing import List, Dict, Set, Tuple + +class Data(BaseModel): + items: List[str] + mapping: Dict[str, int] + unique: Set[str] + pair: Tuple[str, int] +``` + +### With `--use-standard-collections` + +```bash +datamodel-codegen --input schema.json --output models.py --use-standard-collections +``` + +```python +class Data(BaseModel): + items: list[str] + mapping: dict[str, int] + unique: set[str] + pair: tuple[str, int] +``` + +### Compatibility Note + +Built-in generic syntax requires: +- Python 3.10+ at runtime, OR +- `from __future__ import annotations` + +--- + +## `--use-annotated` + +Uses `typing.Annotated` to attach metadata to types, which is the modern approach for Pydantic v2. + +### Without `--use-annotated` + +```python +from pydantic import Field + +class User(BaseModel): + name: str = Field(..., min_length=1, max_length=100) + age: int = Field(..., ge=0, le=150) +``` + +### With `--use-annotated` + +```bash +datamodel-codegen --input schema.json --output models.py --use-annotated +``` + +```python +from typing import Annotated +from pydantic import Field + +class User(BaseModel): + name: Annotated[str, Field(min_length=1, max_length=100)] + age: Annotated[int, Field(ge=0, le=150)] +``` + +### Benefits + +- Cleaner separation of type and constraints +- Better IDE support +- More compatible with other tools that understand `Annotated` +- Required types are more explicit + +--- + +## `--use-generic-container-types` + +Uses abstract container types (`Sequence`, `Mapping`, `FrozenSet`) instead of concrete types (`list`, `dict`, `set`). + +```bash +datamodel-codegen --input schema.json --output models.py --use-generic-container-types +``` + +```python +from typing import Mapping, Sequence + +class Data(BaseModel): + items: Sequence[str] + mapping: Mapping[str, int] +``` + +If `--use-standard-collections` is also set, imports from `collections.abc` instead of `typing`. + +This is useful when: +- You want to use abstract types for better type flexibility +- Maintaining compatibility with interfaces that accept any sequence/mapping + +--- + +## `--disable-future-imports` + +Prevents adding `from __future__ import annotations` to generated files. + +### Default behavior (with future imports) + +```python +from __future__ import annotations + +class User(BaseModel): + friends: list[User] # Forward reference works due to PEP 563 +``` + +### With `--disable-future-imports` + +```bash +datamodel-codegen --input schema.json --output models.py --disable-future-imports +``` + +```python +from typing import List, TYPE_CHECKING + +if TYPE_CHECKING: + from typing import ForwardRef + +class User(BaseModel): + friends: List["User"] # String forward reference +``` + +### When to disable + +- Compatibility with runtime annotation inspection +- Libraries that don't support `__future__.annotations` +- Pydantic v1 in some configurations +- When using `get_type_hints()` at runtime + +--- + +## Common Patterns + +### Pattern 1: Modern Python (3.10+) + +For projects targeting Python 3.10 or later: + +```bash +datamodel-codegen --input schema.json --output models.py \ + --target-python-version 3.10 \ + --use-union-operator \ + --use-standard-collections \ + --use-annotated +``` + +Output: +```python +from typing import Annotated +from pydantic import BaseModel, Field + +class User(BaseModel): + id: int + name: Annotated[str, Field(min_length=1)] + tags: list[str] + metadata: dict[str, str] | None = None +``` + +### Pattern 2: Minimum Supported Python (3.10) + +For projects targeting Python 3.10 (minimum supported version): + +```bash +datamodel-codegen --input schema.json --output models.py \ + --target-python-version 3.10 +``` + +Output: +```python +class User(BaseModel): + id: int + name: str + tags: list[str] + metadata: dict[str, str] | None = None +``` + +### Pattern 3: Maximum compatibility + +For libraries that need to work across multiple Python versions (3.10+): + +```bash +datamodel-codegen --input schema.json --output models.py \ + --target-python-version 3.10 +``` + +The generator will use modern Python 3.10+ syntax including union operators and built-in generic types. + +### Pattern 4: CI/CD consistency + +Pin the Python version in `pyproject.toml` to ensure consistent output: + +```toml +[tool.datamodel-codegen] +target-python-version = "3.10" +use-union-operator = true +use-standard-collections = true +use-annotated = true +``` + +--- + +## Version Feature Matrix + +| Feature | 3.10 | 3.11 | 3.12+ | +|---------|------|------|-------| +| `list[T]` syntax | native | native | native | +| `X \| Y` union | native | native | native | +| `Annotated` | native | native | native | +| `TypeAlias` | native | native | native | +| `Self` | `typing_extensions` | native | native | +| `type` statement | N/A | N/A | native | + +--- + +## Troubleshooting + +### TypeError: 'type' object is not subscriptable + +This occurs when using `list[T]` syntax on older Python versions without `__future__` imports. + +**Solution:** Ensure you are running Python 3.10+ or use `from __future__ import annotations`. + +### Pydantic validation fails with forward references + +This can happen when `__future__.annotations` interacts poorly with Pydantic's type resolution. + +**Solution:** Try `--disable-future-imports` or update to Pydantic v2. + +### Python 3.13 DeprecationWarning with `typing._eval_type` + +When running on Python 3.13+ with `from __future__ import annotations`, you may see: + +```text +DeprecationWarning: Failing to pass a value to the 'type_params' parameter +of 'typing._eval_type' is deprecated... +``` + +This occurs because Python 3.13 deprecated calling `typing._eval_type()` without the `type_params` parameter. Libraries that evaluate forward references (like older Pydantic versions) trigger this warning. + +**Solutions:** + +1. **Upgrade Pydantic** (recommended): + - Pydantic v1: Upgrade to version 1.10.18 or later + - Pydantic v2: Upgrade to the latest version + +2. **Use `--disable-future-imports`** as a workaround: + ```bash + datamodel-codegen --input schema.json --output models.py --disable-future-imports + ``` + +3. **Suppress the warning** in pytest (temporary fix): + ```toml + # pyproject.toml + [tool.pytest.ini_options] + filterwarnings = [ + # For Pydantic v2's v1 compatibility layer (pydantic.v1) + "ignore::DeprecationWarning:pydantic.v1.typing", + # For standalone Pydantic v1 + "ignore::DeprecationWarning:pydantic.typing", + ] + ``` + +!!! note + Python 3.14+ will use native deferred annotations (PEP 649), and the generator + will no longer add `from __future__ import annotations` for those versions. + +### IDE shows type errors + +Some IDEs don't fully understand `from __future__ import annotations`. + +**Solution:** Configure your IDE's Python version or use explicit type syntax matching your runtime version. + +--- + +## See Also + +- [CLI Reference: `--target-python-version`](cli-reference/model-customization.md#target-python-version) +- [CLI Reference: `--use-union-operator`](cli-reference/typing-customization.md#use-union-operator) +- [CLI Reference: `--use-standard-collections`](cli-reference/typing-customization.md#use-standard-collections) +- [CLI Reference: `--use-annotated`](cli-reference/typing-customization.md#use-annotated) +- [Output Model Types](what_is_the_difference_between_v1_and_v2.md) +- [Type Mappings and Custom Types](type-mappings.md) +- [CI/CD Integration](ci-cd.md) + +--- + +# Root Models and Type Aliases + +Source: https://datamodel-code-generator.koxudaxi.dev/root-model-and-type-alias/ + +When a schema defines a simple type (not an object with properties), `datamodel-code-generator` creates a root model. If you don't want to introduce a new level of attribute access (`.root`) or want to use generated types as plain Python types in non-Pydantic code, you can use the `--use-type-alias` flag to generate type aliases instead of root models. + +## โš ๏ธ Notes and Limitations + +**This functionality is experimental!** Here are a few known issues: + +- ๐Ÿ“Œ RootModel and type aliases do not fully support field-specific metadata (default, alias, etc). See [Named Type Aliases](https://docs.pydantic.dev/latest/concepts/types/#named-type-aliases) for details. +- ๐Ÿšซ Type aliases do not support some RootModel features (e.g. `model_config`) +- ๐Ÿ“„ A RootModel or type alias is also generated for the main schema, allowing you to define a single type alias from a schema file (e.g. `model.json` containing `{"title": "MyString", "type": "string"}`) +- โŒ Type aliases cannot be combined with `Annotated` for Pydantic v1 + +## ๐Ÿ“Š Type Alias Behavior by Output Type and Python Version + +The type of type alias generated depends on the output model type and target Python version: + +| Output Type | Python 3.12+ | Python 3.10-3.11 | +|-------------|--------------|------------------| +| **Pydantic v2** | `type` statement | `TypeAliasType` (typing_extensions) | +| **Pydantic v1** | `TypeAlias` | `TypeAlias` | +| **TypedDict** | `type` statement | `TypeAlias` | +| **dataclasses** | `type` statement | `TypeAlias` | +| **msgspec** | `type` statement | `TypeAlias` | + +### ๐Ÿค” Why the difference? + +- **Pydantic v2** requires `TypeAliasType` because it cannot properly handle `TypeAlias` annotations +- **Other output types** (TypedDict, dataclasses, msgspec) use `TypeAlias` for better compatibility with libraries that may not expect `TypeAliasType` objects +- **Python 3.12+** uses the native `type` statement for all output types + +## ๐Ÿ“ Example + +### model.json + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "UserId": { + "type": "string" + }, + "Status": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"} + ] + }, + "User": { + "type": "object", + "properties": { + "id": {"$ref": "#/definitions/UserId"}, + "status": {"$ref": "#/definitions/Status"} + } + } + } +} +``` + +### ๐Ÿ”น Pydantic v1 + +#### Generating RootModel + +```bash +datamodel-codegen --input model.json --input-file-type jsonschema --output model.py +``` + +### โœจ Generated model.py (Pydantic v1) + +```python +# generated by datamodel-codegen: +# filename: model.json + +from __future__ import annotations + +from typing import Any, Optional, Union + +from pydantic import BaseModel + + +class Model(BaseModel): + __root__: Any + + +class UserId(BaseModel): + __root__: str + + +class Status(BaseModel): + __root__: Union[str, int] + + +class User(BaseModel): + id: Optional[UserId] = None + status: Optional[Status] = None +``` + +#### Generating TypeAlias annotation + +```bash +datamodel-codegen --input model.json --input-file-type jsonschema --use-type-alias --output model.py +``` + +### โœจ Generated model.py (Python 3.10+) + +```python +# generated by datamodel-codegen: +# filename: model.json + +from __future__ import annotations + +from typing import Any, Optional, TypeAlias, Union + +from pydantic import BaseModel + +Model: TypeAlias = Any + + +UserId: TypeAlias = str + + +Status: TypeAlias = Union[str, int] + + +class User(BaseModel): + id: Optional[UserId] = None + status: Optional[Status] = None +``` + +### ๐Ÿ”ธ Pydantic v2 + +#### Generating RootModel + +```bash +datamodel-codegen --input model.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --output model.py +``` + +### โœจ Generated model.py (Pydantic v2) + +```python +# generated by datamodel-codegen: +# filename: model.json + +from __future__ import annotations + +from typing import Any, Optional, Union + +from pydantic import BaseModel, RootModel + + +class Model(RootModel[Any]): + root: Any + + +class UserId(RootModel[str]): + root: str + + +class Status(RootModel[Union[str, int]]): + root: Union[str, int] + + +class User(BaseModel): + id: Optional[UserId] = None + status: Optional[Status] = None +``` + +#### Generating type statement (Python 3.12+) + +```bash +datamodel-codegen --input model.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --use-type-alias --target-python-version 3.12 --output model.py +``` + +### โœจ Generated model.py (Python 3.12+ type statement) + +```python +# generated by datamodel-codegen: +# filename: model.json + +from __future__ import annotations + +from typing import Any, Optional, Union + +from pydantic import BaseModel + +type Model = Any + + +type UserId = str + + +type Status = Union[str, int] + + +class User(BaseModel): + id: Optional[UserId] = None + status: Optional[Status] = None +``` + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--use-type-alias`](cli-reference/typing-customization.md#use-type-alias) - Detailed CLI option documentation +- ๐ŸŽฏ [CLI Reference: `--target-python-version`](cli-reference/model-customization.md#target-python-version) - Control Python version-specific syntax + +--- + +# Field Constraints + +Source: https://datamodel-code-generator.koxudaxi.dev/field-constraints/ + + + +# ๐Ÿ”’ Field Constraints + +The `--field-constraints` option converts all `con*` annotations (like `conint`, `constr`) to `Field` constraint options. + +## ๐Ÿค” Why use this? + +Mypy may show errors for `con*` annotations on fields. The `--field-constraints` option resolves this problem by using standard `Field()` constraints instead. + +## ๐Ÿ“ Example + +Convert simple JSON Schema `model.json` to pydantic model `model.py`: + +**model.json** +```json +{ + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 64 + } + }, + "required": ["name"] +} +``` + +### โŒ Without `--field-constraints` option + +```bash +datamodel-codegen --input model.json --input-file-type jsonschema > model.py +``` + +**Generated model.py** +```python +# generated by datamodel-codegen: +# filename: model.json +# timestamp: 2020-07-20T15:37:56+00:00 + +from __future__ import annotations + +from pydantic import BaseModel, constr + + +class Model(BaseModel): + name: constr(max_length=64) +``` + +**๐Ÿ”ด Run mypy...** +```bash +$ mypy model.py +model.py:3: error: Invalid type comment or annotation +model.py:3: note: Suggestion: use constr[...] instead of constr(...) +Found 1 error in 1 file (checked 1 source file) +``` + +mypy shows errors! ๐Ÿ˜ฑ + +--- + +### โœ… With `--field-constraints` option + +```bash +datamodel-codegen --input model.json --input-file-type jsonschema --field-constraints > model.py +``` + +**Generated model.py** +```python +# generated by datamodel-codegen: +# filename: model.json +# timestamp: 2020-07-20T15:47:21+00:00 + +from __future__ import annotations + +from pydantic import BaseModel, Field + + +class Model(BaseModel): + name: str = Field(..., max_length=64) +``` + +**๐ŸŸข Run mypy...** +```bash +$ mypy model.py +Success: no issues found in 1 source file +``` + +No errors! ๐ŸŽ‰ + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--field-constraints`](cli-reference/field-customization.md#field-constraints) - Detailed CLI option documentation with examples + +## ๐Ÿ”— Related Issues + +- [pydantic/pydantic#156](https://github.com/samuelcolvin/pydantic/issues/156) + +--- + +# Field Aliases + +Source: https://datamodel-code-generator.koxudaxi.dev/aliases/ + + + +# ๐Ÿท๏ธ Field Aliases + +The `--aliases` option allows you to rename fields in the generated models. This is useful when you want to use different Python field names than those defined in the schema while preserving the original names as serialization aliases. + +## ๐Ÿš€ Basic Usage + +```bash +datamodel-codegen --input schema.json --output model.py --aliases aliases.json +``` + +## ๐Ÿ“‹ Alias File Format + +The alias file is a JSON file that maps original field names to their Python aliases. + +### ๐Ÿ“ Flat Format (Traditional) + +The simplest format applies aliases to all fields with the matching name, regardless of which class they belong to: + +```json +{ + "id": "id_", + "type": "type_", + "class": "class_" +} +``` + +This will rename all fields named `id` to `id_`, all fields named `type` to `type_`, etc. + +### ๐ŸŽฏ Scoped Format (Class-Specific) + +When you have the same field name in multiple classes but want different aliases for each, use the scoped format with `ClassName.field`: + +```json +{ + "User.name": "user_name", + "Address.name": "address_name", + "name": "default_name" +} +``` + +**โšก Priority**: Scoped aliases take priority over flat aliases. In the example above: + +- `User.name` will be renamed to `user_name` +- `Address.name` will be renamed to `address_name` +- Any other class with a `name` field will use `default_name` + +## ๐Ÿ“ Example + +### ๐Ÿ“ฅ Input Schema + +```json +{ + "type": "object", + "title": "Root", + "properties": { + "name": {"type": "string"}, + "user": { + "type": "object", + "title": "User", + "properties": { + "name": {"type": "string"}, + "id": {"type": "integer"} + } + }, + "address": { + "type": "object", + "title": "Address", + "properties": { + "name": {"type": "string"}, + "city": {"type": "string"} + } + } + } +} +``` + +### ๐Ÿท๏ธ Alias File + +```json +{ + "Root.name": "root_name", + "User.name": "user_name", + "Address.name": "address_name" +} +``` + +### โœจ Generated Output + +```python +from pydantic import BaseModel, Field + +class User(BaseModel): + user_name: str | None = Field(None, alias='name') + id: int | None = None + +class Address(BaseModel): + address_name: str | None = Field(None, alias='name') + city: str | None = None + +class Root(BaseModel): + root_name: str | None = Field(None, alias='name') + user: User | None = None + address: Address | None = None +``` + +## ๐Ÿ“Œ Notes + +- The `ClassName` in scoped format must match the generated Python class name (after title conversion) +- When using `--use-title-as-name`, the class name is derived from the `title` property in the schema +- Aliases are applied during code generation, so the original field names are preserved as Pydantic `alias` values for proper serialization/deserialization + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--aliases`](cli-reference/field-customization.md#aliases) - Detailed CLI option documentation with examples + +--- + +# Field Validators + +Source: https://datamodel-code-generator.koxudaxi.dev/validators/ + + + +# Field Validators + +The `--validators` option allows you to add custom field validators to generated Pydantic v2 models. This enables you to inject validation logic into generated code without manually editing it. + +## Basic Usage + +```bash +datamodel-codegen --input schema.json --output model.py \ + --validators validators.json \ + --output-model-type pydantic_v2.BaseModel +``` + +## Validators File Format + +The validators file is a JSON file that maps model names to their validator definitions. + +### Structure + +```json +{ + "ModelName": { + "validators": [ + { + "field": "field_name", + "function": "module.path.to.validator_function", + "mode": "after" + } + ] + } +} +``` + +### Fields + +| Field | Description | Required | +|-------|-------------|----------| +| `field` | Single field name to validate | One of `field` or `fields` | +| `fields` | List of field names (for multi-field validators) | One of `field` or `fields` | +| `function` | Fully qualified path to the validator function | Yes | +| `mode` | Validator mode: `before`, `after`, `wrap`, or `plain` | No (default: `after`) | + +## Validator Modes + +Pydantic v2 supports different validator modes, each with its own signature: + +### `before` / `after` Mode + +Standard validators that run before or after Pydantic's own validation: + +```python +def validate_name(v: Any, info: ValidationInfo) -> Any: + if not v: + raise ValueError("Name cannot be empty") + return v.strip() +``` + +### `wrap` Mode + +Wrap validators receive a handler to call the next validator in the chain: + +```python +from pydantic import ValidationInfo, ValidatorFunctionWrapHandler + +def wrap_validate_name( + v: Any, + handler: ValidatorFunctionWrapHandler, + info: ValidationInfo +) -> Any: + # Pre-processing + v = v.strip() if isinstance(v, str) else v + # Call next validator + result = handler(v) + # Post-processing + return result.upper() +``` + +### `plain` Mode + +Plain validators replace Pydantic's validation entirely: + +```python +def plain_validate_name(v: Any) -> str: + if not isinstance(v, str): + raise TypeError("Expected string") + return v +``` + +## Example + +### Input Schema + +```json +{ + "type": "object", + "title": "User", + "properties": { + "name": {"type": "string"}, + "email": {"type": "string", "format": "email"}, + "age": {"type": "integer", "minimum": 0} + }, + "required": ["name", "email"] +} +``` + +### Validators File + +```json +{ + "User": { + "validators": [ + { + "field": "name", + "function": "myapp.validators.validate_name", + "mode": "before" + }, + { + "field": "email", + "function": "myapp.validators.validate_email", + "mode": "after" + }, + { + "fields": ["name", "email"], + "function": "myapp.validators.validate_contact_info", + "mode": "after" + } + ] + } +} +``` + +### Validator Functions (myapp/validators.py) + +```python +from typing import Any +from pydantic import ValidationInfo + +def validate_name(v: Any, info: ValidationInfo) -> Any: + if isinstance(v, str): + return v.strip() + return v + +def validate_email(v: Any, info: ValidationInfo) -> Any: + if isinstance(v, str) and not v.endswith("@example.com"): + # Custom email domain validation + pass + return v + +def validate_contact_info(v: Any, info: ValidationInfo) -> Any: + # This runs for both name and email fields + return v +``` + +### Generated Output + +```python +from __future__ import annotations + +from typing import Any + +from myapp.validators import validate_contact_info, validate_email, validate_name +from pydantic import BaseModel, EmailStr, ValidationInfo, conint, field_validator + + +class User(BaseModel): + name: str + email: EmailStr + age: conint(ge=0) | None = None + + @field_validator('name', mode='before') + @classmethod + def validate_name_validator(cls, v: Any, info: ValidationInfo) -> Any: + return validate_name(v, info) + + @field_validator('email', mode='after') + @classmethod + def validate_email_validator(cls, v: Any, info: ValidationInfo) -> Any: + return validate_email(v, info) + + @field_validator('name', 'email', mode='after') + @classmethod + def validate_contact_info_validator(cls, v: Any, info: ValidationInfo) -> Any: + return validate_contact_info(v, info) +``` + +## Notes + +- This feature only supports Pydantic v2 (`--output-model-type pydantic_v2.BaseModel`) +- The `ModelName` in the validators file must match the generated Python class name +- Validator functions are imported automatically based on the `function` path +- When the same validator function is used multiple times, an incrementing suffix (`_1`, `_2`, etc.) is added to ensure method name uniqueness + +--- + +## See Also + +- [CLI Reference: `--validators`](cli-reference/general-options.md) - CLI option documentation +- [Pydantic v2 Validators Documentation](https://docs.pydantic.dev/latest/concepts/validators/) - Official Pydantic documentation + +--- + +# Custom Class Decorators + +Source: https://datamodel-code-generator.koxudaxi.dev/class-decorators/ + + + +# Custom Class Decorators + +The `--class-decorators` option adds custom decorators to all generated model classes. This is useful for integrating with serialization libraries like `dataclasses_json`, or adding custom behavior to your models. + +## Why use this? + +When using `dataclasses.dataclass` output with `--snake-case-field`, Python field names are snake_case but the original JSON keys may be camelCase. Libraries like `dataclasses_json` can handle this conversion automatically via decorators. + +## Example: Using dataclasses_json + +Convert a JSON Schema with camelCase properties to dataclasses with snake_case fields that serialize back to camelCase. + +**schema.json** +```json +{ + "type": "object", + "title": "User", + "properties": { + "firstName": { "type": "string" }, + "lastName": { "type": "string" }, + "emailAddress": { "type": "string" } + }, + "required": ["firstName", "lastName"] +} +``` + +### Without `--class-decorators` + +```bash +datamodel-codegen --input schema.json \ + --output-model-type dataclasses.dataclass \ + --snake-case-field +``` + +**Generated model.py** +```python +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass +class User: + first_name: str + last_name: str + email_address: str | None = None +``` + +The field names are snake_case, but there's no way to map them back to the original camelCase JSON keys. + +--- + +### With `--class-decorators` + +```bash +datamodel-codegen --input schema.json \ + --output-model-type dataclasses.dataclass \ + --snake-case-field \ + --class-decorators "@dataclass_json(letter_case=LetterCase.CAMEL)" \ + --additional-imports "dataclasses_json.dataclass_json,dataclasses_json.LetterCase" +``` + +**Generated model.py** +```python +from __future__ import annotations + +from dataclasses import dataclass + +from dataclasses_json import LetterCase, dataclass_json + + +@dataclass_json(letter_case=LetterCase.CAMEL) +@dataclass +class User: + first_name: str + last_name: str + email_address: str | None = None +``` + +Now serialization automatically converts between snake_case and camelCase: + +```python +user = User(first_name="John", last_name="Doe") +print(user.to_json()) +# {"firstName": "John", "lastName": "Doe", "emailAddress": null} +``` + +## Usage Notes + +- **Multiple decorators**: Use comma separation for multiple decorators: + ```bash + --class-decorators "@decorator1,@decorator2" + ``` + +- **@ prefix is optional**: Both `@dataclass_json` and `dataclass_json` work - the `@` is added automatically if missing. + +- **Combine with `--additional-imports`**: Always add the required imports for your decorators using `--additional-imports`. + +## Other Use Cases + +The `--class-decorators` option works with any output model type: + +- **Pydantic models**: Add custom validators or behavior +- **TypedDict**: Add runtime type-checking decorators +- **msgspec.Struct**: Add custom serialization hooks + +## See Also + +- [CLI Reference: `--class-decorators`](cli-reference/template-customization.md#class-decorators) - Detailed CLI option documentation +- [CLI Reference: `--additional-imports`](cli-reference/template-customization.md#additional-imports) - Adding custom imports + +## Related Issues + +- [#2358](https://github.com/koxudaxi/datamodel-code-generator/issues/2358) - Feature request for dataclasses_json support + +--- + +# OpenAPI-Specific Options + +Source: https://datamodel-code-generator.koxudaxi.dev/openapi-options/ + + + +# OpenAPI-Specific Options + +When working with OpenAPI specifications, datamodel-code-generator provides several options to control how schemas, operations, and special properties are handled. This page explains when and how to use each option. + +## Quick Overview + +| Option | Description | +|--------|-------------| +| `--openapi-scopes` | Select which parts of the spec to generate models from | +| `--include-path-parameters` | Include path parameters in generated models | +| `--use-operation-id-as-name` | Name models using operation IDs | +| `--read-only-write-only-model-type` | Generate separate models for read/write contexts | +| `--validation` | Enable OpenAPI validation constraints (deprecated) | + +--- + +## `--openapi-scopes` + +Controls which sections of the OpenAPI specification to generate models from. + +| Scope | Description | +|-------|-------------| +| `schemas` | Generate from `#/components/schemas` (default) | +| `parameters` | Generate from `#/components/parameters` | +| `paths` | Generate from path operation parameters | + +### Default behavior (schemas only) + +```bash +datamodel-codegen --input openapi.yaml --output models.py +``` + +Generates models only from `#/components/schemas`. + +### Include parameters + +```bash +datamodel-codegen --input openapi.yaml --output models.py \ + --openapi-scopes schemas parameters +``` + +Also generates models from `#/components/parameters`. + +### Include path-level definitions + +```bash +datamodel-codegen --input openapi.yaml --output models.py \ + --openapi-scopes schemas parameters paths +``` + +Generates models from all sources, including inline path operation parameters. + +### When to use each scope + +| Use Case | Recommended Scopes | +|----------|-------------------| +| Basic model generation | `schemas` (default) | +| Reusable parameter types | `schemas parameters` | +| Complete API coverage | `schemas parameters paths` | + +--- + +## `--include-path-parameters` + +Includes path parameters as fields in generated models. + +### OpenAPI Example + +```yaml +paths: + /users/{user_id}/orders/{order_id}: + get: + operationId: getOrder + parameters: + - name: user_id + in: path + schema: + type: string + - name: order_id + in: path + schema: + type: integer +``` + +### Without `--include-path-parameters` + +```python +class GetOrderResponse(BaseModel): + # Only response body fields + items: list[Item] + total: float +``` + +### With `--include-path-parameters` + +```bash +datamodel-codegen --input openapi.yaml --output models.py --include-path-parameters +``` + +```python +class GetOrderResponse(BaseModel): + user_id: str + order_id: int + items: list[Item] + total: float +``` + +### When to use + +- Building request validation models that include URL parameters +- Creating unified request/response types for API clients +- Generating models for frameworks that expect all parameters in one object + +--- + +## `--use-operation-id-as-name` + +Uses the `operationId` from OpenAPI operations to name generated models instead of deriving names from paths. + +### OpenAPI Example + +```yaml +paths: + /users/{id}: + get: + operationId: getUserById + responses: + '200': + content: + application/json: + schema: + type: object + properties: + id: { type: integer } + name: { type: string } +``` + +### Without `--use-operation-id-as-name` + +```python +class UsersIdGetResponse(BaseModel): # Derived from path + id: int + name: str +``` + +### With `--use-operation-id-as-name` + +```bash +datamodel-codegen --input openapi.yaml --output models.py --use-operation-id-as-name +``` + +```python +class GetUserByIdResponse(BaseModel): # Uses operationId + id: int + name: str +``` + +### When to use + +- When `operationId` values are well-designed and descriptive +- For consistency with generated API clients (e.g., OpenAPI Generator) +- When path-derived names are too verbose or unclear + +--- + +## `--read-only-write-only-model-type` + +Generates separate model variants for properties marked as `readOnly` or `writeOnly` in OpenAPI. + +### OpenAPI Example + +```yaml +components: + schemas: + User: + type: object + properties: + id: + type: integer + readOnly: true # Only in responses + password: + type: string + writeOnly: true # Only in requests + name: + type: string # In both +``` + +### Without `--read-only-write-only-model-type` + +```python +class User(BaseModel): + id: Optional[int] = None # Both included + password: Optional[str] = None + name: Optional[str] = None +``` + +### With `--read-only-write-only-model-type` + +```bash +datamodel-codegen --input openapi.yaml --output models.py \ + --read-only-write-only-model-type all +``` + +```python +class User(BaseModel): + """Base model with all fields.""" + id: Optional[int] = None + password: Optional[str] = None + name: Optional[str] = None + +class UserRead(BaseModel): + """For responses - excludes writeOnly fields.""" + id: Optional[int] = None + name: Optional[str] = None + +class UserWrite(BaseModel): + """For requests - excludes readOnly fields.""" + password: Optional[str] = None + name: Optional[str] = None +``` + +### Values + +| Value | Description | +|-------|-------------| +| `all` | Generate both Read and Write variants | +| `read` | Generate only Read variants | +| `write` | Generate only Write variants | + +### When to use + +- APIs with distinct request/response schemas +- Strict type checking for API clients +- When `readOnly`/`writeOnly` properties are heavily used + +--- + +## `--validation` (Deprecated) + +!!! warning "Deprecated" + Use `--field-constraints` instead. The `--validation` option is maintained for backward compatibility. + +Enables validation constraints from OpenAPI schemas. + +```bash +# Deprecated +datamodel-codegen --input openapi.yaml --output models.py --validation + +# Recommended +datamodel-codegen --input openapi.yaml --output models.py --field-constraints +``` + +See [Field Constraints](field-constraints.md) for details. + +--- + +## Common Patterns + +### Pattern 1: Basic API models + +For simple APIs where you only need schema models: + +```bash +datamodel-codegen --input openapi.yaml --output models.py +``` + +### Pattern 2: Full API client models + +For generating complete models for an API client: + +```bash +datamodel-codegen --input openapi.yaml --output models/ \ + --openapi-scopes schemas parameters paths \ + --use-operation-id-as-name \ + --include-path-parameters +``` + +### Pattern 3: Strict request/response separation + +For APIs with distinct input/output shapes: + +```bash +datamodel-codegen --input openapi.yaml --output models/ \ + --read-only-write-only-model-type all \ + --field-constraints +``` + +### Pattern 4: Versioned API structure + +For large APIs with versioned endpoints: + +```bash +datamodel-codegen --input openapi.yaml --output models/ \ + --treat-dot-as-module \ + --use-operation-id-as-name \ + --all-exports-scope recursive +``` + +--- + +## OpenAPI Version Support + +| OpenAPI Version | Support | +|-----------------|---------| +| 3.0.x | Full support | +| 3.1.x | Full support | +| 2.0 (Swagger) | Partial support | + +--- + +## See Also + +- [CLI Reference: OpenAPI-only Options](cli-reference/openapi-only-options.md) +- [Field Constraints](field-constraints.md) +- [Module Structure and Exports](module-exports.md) +- [OpenAPI Input Format](openapi.md) + +--- + +# Custom Templates + +Source: https://datamodel-code-generator.koxudaxi.dev/custom_template/ + + + +# ๐ŸŽจ Custom Templates + +One of the powerful features of datamodel-code-generator is the ability to use custom templates with the `--custom-template-dir` option. This allows you to provide a directory containing Jinja2 templates for customizing the generated code. + +## ๐Ÿš€ Usage + +Pass the directory path containing your custom templates: + +```bash +datamodel-codegen --input {your_input_file} --output {your_output_file} --custom-template-dir {your_custom_template_directory} +``` + +## ๐Ÿ“ Example + +Let's say you want to generate a custom Python data model from a JSON Schema file called `person.json`. You want the generated data model to include a custom comment at the top of the file. + +### 1๏ธโƒฃ Create the template directory + +Create a directory structure matching the output model type: + +``` +custom_templates/ +โ””โ”€โ”€ pydantic/ + โ””โ”€โ”€ BaseModel.jinja2 +``` + +### 2๏ธโƒฃ Create the template + +**custom_templates/pydantic/BaseModel.jinja2** +```jinja2 +# This is a custom comment generated with custom_template!! + +class {{ class_name }}({{ base_class }}): +{%- for field in fields %} + {{ field.name }}: {{ field.type_hint }} +{%- endfor -%} +``` + +This custom template includes the custom comment at the top and replicates the default rendering behavior of the `BaseModel.jinja2` template. + +### 3๏ธโƒฃ Run the generator + +```bash +datamodel-codegen --input person.json --output person.py --custom-template-dir custom_templates +``` + +### โœจ Generated Output + +**person.py** +```python +# generated by datamodel-codegen: +# filename: person.json +# timestamp: 2023-04-09T05:36:24+00:00 + +from __future__ import annotations + +from typing import Optional + +from pydantic import BaseModel + +# This is a custom comment generated with custom_template!! + + +class Model(BaseModel): + name: Optional[str] + age: Optional[int] + +``` + +## ๐Ÿ“š Template Reference + +You can create more complex custom templates by copying [the default templates](https://github.com/koxudaxi/datamodel-code-generator/tree/main/src/datamodel_code_generator/model/template). Use them as a reference for understanding the structure and available variables, and customize the code generation process according to your specific requirements. + +--- + +## ๐Ÿ”ง Schema Extensions + +OpenAPI and JSON Schema allow custom extension fields prefixed with `x-`. These schema extensions are automatically passed to templates via the `extensions` variable, enabling dynamic code generation based on your custom schema metadata. + +### Example: Database Model Configuration + +Suppose you want to add a `__collection__` class attribute based on a custom `x-database-model` extension in your OpenAPI schema: + +**api.yaml** +```yaml +openapi: "3.0.0" +info: + version: 1.0.0 + title: My API +paths: {} +components: + schemas: + User: + type: object + x-database-model: + collection: users + indexes: + - email + properties: + id: + type: string + email: + type: string + required: + - id + - email +``` + +**custom_templates/pydantic_v2/BaseModel.jinja2** +```jinja2 +class {{ class_name }}({{ base_class }}): +{%- if extensions is defined and extensions.get('x-database-model') %} + __collection__ = "{{ extensions['x-database-model']['collection'] }}" +{%- endif %} +{%- for field in fields %} + {{ field.name }}: {{ field.type_hint }} +{%- endfor %} +``` + +**Run the generator** +```bash +datamodel-codegen --input api.yaml --output models.py \ + --custom-template-dir custom_templates \ + --output-model-type pydantic_v2.BaseModel +``` + +**Generated Output** +```python +from __future__ import annotations + +from pydantic import BaseModel + + +class User(BaseModel): + __collection__ = "users" + id: str + email: str +``` + +### Available Extensions + +Any field starting with `x-` in your schema will be available in the `extensions` dictionary: + +| Schema Field | Template Access | +|--------------|-----------------| +| `x-database-model` | `extensions['x-database-model']` | +| `x-custom-flag` | `extensions['x-custom-flag']` | +| `x-my-extension` | `extensions['x-my-extension']` | + +### Use Cases + +- **Database mapping**: Add collection names, indexes, or ORM configurations +- **Validation rules**: Include custom validation logic based on schema metadata +- **Documentation**: Generate custom docstrings or comments from schema extensions +- **Framework integration**: Add framework-specific decorators or attributes + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--custom-template-dir`](cli-reference/template-customization.md#custom-template-dir) - Detailed CLI option documentation +- ๐Ÿ“Š [CLI Reference: `--extra-template-data`](cli-reference/template-customization.md#extra-template-data) - Pass custom variables to templates + +--- + +# Custom Code Formatters + +Source: https://datamodel-code-generator.koxudaxi.dev/custom-formatters/ + + + +# ๐ŸŽจ Custom Code Formatters + +Create your own custom code formatters for specialized formatting needs. + +## ๐Ÿš€ Usage + +Pass the module path containing your formatter class: + +```bash +datamodel-codegen --input {your_input_file} --output {your_output_file} --custom-formatters "{path_to_your_module}.your_module" +``` + +## ๐Ÿ“ Example + +### 1๏ธโƒฃ Create your formatter + +### your_module.py + +```python +from datamodel_code_generator.format import CustomCodeFormatter + +class CodeFormatter(CustomCodeFormatter): + def apply(self, code: str) -> str: + # Apply your custom formatting here + # For example, add a custom header comment: + header = "# This code was formatted by custom formatter\n" + return header + code +``` + +### 2๏ธโƒฃ Use your formatter + +```bash +datamodel-codegen --input schema.json --output model.py --custom-formatters "mypackage.your_module" +``` + +## ๐Ÿ”ง Passing Arguments + +You can pass keyword arguments to your custom formatter using `--custom-formatters-kwargs`: + +```bash +datamodel-codegen --input schema.json --output model.py \ + --custom-formatters "mypackage.your_module" \ + --custom-formatters-kwargs '{"line_length": 100}' +``` + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--custom-formatters`](cli-reference/template-customization.md#custom-formatters) - Detailed CLI option documentation +- ๐Ÿ”ง [CLI Reference: `--custom-formatters-kwargs`](cli-reference/template-customization.md#custom-formatters-kwargs) - Pass arguments to custom formatters +- ๐Ÿ–Œ๏ธ [Formatting](formatting.md) - Built-in code formatting with black and isort + +--- + +# Code Formatting + +Source: https://datamodel-code-generator.koxudaxi.dev/formatting/ + + + +# ๐Ÿ–Œ๏ธ Code Formatting + +Generated code is automatically formatted using code formatters. By default, `black` and `isort` are used to produce consistent, well-formatted output. + +## ๐ŸŽฏ Default Behavior + +!!! warning "Future Change" + In a future version, the default formatters will change from `black` and `isort` to `ruff`. + To prepare for this change, consider switching to ruff now using `--formatters ruff-format ruff-check`. + + **CLI users**: To suppress this warning, use `--disable-warnings` or explicitly specify `--formatters black isort`. + + **Library users**: Explicitly pass `formatters=[Formatter.BLACK, Formatter.ISORT]` to suppress this warning. + +```bash +datamodel-codegen --input schema.yaml --output model.py +``` + +This runs the following formatters in order: + +1. **isort** - Sorts and organizes imports +2. **black** - Formats code style + +## ๐Ÿ› ๏ธ Available Formatters + +| Formatter | Description | +|-----------|-------------| +| `black` | Code formatting (PEP 8 style) | +| `isort` | Import sorting | +| `ruff-check` | Linting with auto-fix | +| `ruff-format` | Fast code formatting (black alternative) | + +### โšก Using ruff instead of black + +[Ruff](https://github.com/astral-sh/ruff) is a fast Python linter and formatter. To use it: + +!!! note "Installation Required" + ruff is an optional dependency. Install it with: + ```bash + pip install 'datamodel-code-generator[ruff]' + ``` + +```bash +# Use ruff for both linting and formatting +datamodel-codegen --formatters ruff-check ruff-format --input schema.yaml --output model.py + +# Use ruff-format as a black replacement +datamodel-codegen --formatters isort ruff-format --input schema.yaml --output model.py +``` + +### ๐Ÿšซ Disable formatting + +`datamodel-codegen` requires at least one formatter when using the CLI `--formatters` option. + +To disable built-in formatting entirely, configure it via `pyproject.toml`: + +```toml title="pyproject.toml" +[tool.datamodel-codegen] +formatters = [] +``` + +## โš™๏ธ Configuration via pyproject.toml + +Formatters read their configuration from `pyproject.toml`. The tool searches for `pyproject.toml` in: + +1. The output file's directory +2. Parent directories (up to the git repository root) + +### ๐Ÿ“ Example Configuration + +```toml title="pyproject.toml" +[tool.black] +line-length = 100 +skip-string-normalization = true + +[tool.isort] +profile = "black" +line_length = 100 + +[tool.ruff] +line-length = 100 + +[tool.ruff.format] +quote-style = "single" +``` + +## ๐Ÿ’ฌ String Quotes + +By default, string quote style is determined by your formatter configuration. To force double quotes regardless of configuration: + +```bash +datamodel-codegen --use-double-quotes --input schema.yaml --output model.py +``` + +This overrides `skip_string_normalization` in black config. + +## ๐ŸŽจ Custom Formatters + +You can create custom formatters for specialized formatting needs. See [Custom Formatters](custom-formatters.md) for details. + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--formatters`](cli-reference/template-customization.md#formatters) - Specify code formatters +- ๐Ÿ’ฌ [CLI Reference: `--use-double-quotes`](cli-reference/template-customization.md#use-double-quotes) - Force double quotes +- ๐ŸŽจ [Custom Formatters](custom-formatters.md) - Create your own formatters +- โš™๏ธ [pyproject.toml Configuration](pyproject_toml.md) - Configure datamodel-codegen options + +--- + +# One-liner Usage + +Source: https://datamodel-code-generator.koxudaxi.dev/oneliner/ + +This guide covers how to use datamodel-code-generator with pipes and clipboard tools for quick, one-time code generation without permanent installation. + +!!! note + The package name is `datamodel-code-generator`, and the CLI command is `datamodel-codegen`. + +--- + +## One-liner Execution with uvx/pipx + +You don't need to install datamodel-code-generator permanently. Use `uvx` or `pipx run` to execute it directly. + +### Using uvx (Recommended) + +[uvx](https://docs.astral.sh/uv/guides/tools/) runs Python tools without installation: + +```bash +# Basic usage +uvx datamodel-codegen --input schema.json --output model.py + +# With extras (e.g., HTTP support) +uvx --from 'datamodel-code-generator[http]' datamodel-codegen --url https://example.com/api.yaml --output model.py + +# With GraphQL support +uvx --from 'datamodel-code-generator[graphql]' datamodel-codegen --input schema.graphql --output model.py +``` + +### Using pipx run + +[pipx](https://pipx.pypa.io/) also supports one-shot execution: + +```bash +pipx run datamodel-code-generator --input schema.json --output model.py +``` + +--- + +## Reading from stdin + +datamodel-code-generator can read schema input from stdin, enabling powerful pipeline workflows: + +```bash +# Pipe JSON directly +echo '{"type": "object", "properties": {"name": {"type": "string"}}}' | \ + uvx datamodel-codegen --input-file-type jsonschema + +# Pipe from another command +curl -s https://example.com/schema.json | \ + uvx datamodel-codegen --input-file-type jsonschema --output model.py +``` + +--- + +## Clipboard Integration + +Combine stdin support with clipboard tools to quickly generate models from copied schema definitions. + +### macOS (pbpaste/pbcopy) + +```bash +# Generate from clipboard and print to stdout +pbpaste | uvx datamodel-codegen --input-file-type jsonschema + +# Generate from clipboard and save to file +pbpaste | uvx datamodel-codegen --input-file-type jsonschema --output model.py + +# Generate from clipboard and copy result back to clipboard +pbpaste | uvx datamodel-codegen --input-file-type jsonschema | pbcopy +``` + +### Linux (xclip/xsel) + +=== "xclip" + + ```bash + # Generate from clipboard and print to stdout + xclip -selection clipboard -o | uvx datamodel-codegen --input-file-type jsonschema + + # Generate and copy result to clipboard + xclip -selection clipboard -o | uvx datamodel-codegen --input-file-type jsonschema | xclip -selection clipboard + ``` + +=== "xsel" + + ```bash + # Generate from clipboard and print to stdout + xsel --clipboard --output | uvx datamodel-codegen --input-file-type jsonschema + + # Generate and copy result to clipboard + xsel --clipboard --output | uvx datamodel-codegen --input-file-type jsonschema | xsel --clipboard --input + ``` + +!!! tip "Installing clipboard tools on Linux" + ```bash + # Debian/Ubuntu + sudo apt install xclip + # or + sudo apt install xsel + + # Fedora + sudo dnf install xclip + # or + sudo dnf install xsel + ``` + +### Windows (clip/PowerShell) + +=== "PowerShell" + + ```powershell + # Generate from clipboard and print to stdout + Get-Clipboard | uvx datamodel-codegen --input-file-type jsonschema + + # Generate and copy result to clipboard + Get-Clipboard | uvx datamodel-codegen --input-file-type jsonschema | Set-Clipboard + ``` + +=== "Command Prompt" + + ```batch + REM Windows Command Prompt doesn't have a built-in paste command + REM Use PowerShell from cmd: + powershell -command "Get-Clipboard" | uvx datamodel-codegen --input-file-type jsonschema + ``` + +!!! note "Windows clip command" + The `clip` command on Windows only supports copying **to** the clipboard, not reading from it. Use PowerShell's `Get-Clipboard` and `Set-Clipboard` for full clipboard integration. + +--- + +## Practical Examples + +### Quick model generation workflow + +1. Copy a JSON Schema from documentation or an API response +2. Run the generator from clipboard: + +```bash +# macOS +pbpaste | uvx datamodel-codegen --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel + +# Linux +xclip -selection clipboard -o | uvx datamodel-codegen --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel + +# Windows PowerShell +Get-Clipboard | uvx datamodel-codegen --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel +``` + +### Generating from API documentation + +```bash +# Fetch OpenAPI spec and generate models +curl -s https://petstore3.swagger.io/api/v3/openapi.json | \ + uvx datamodel-codegen --input-file-type openapi --output-model-type pydantic_v2.BaseModel --output petstore.py +``` + +### Generating from GitHub raw URLs + +You can directly fetch schemas from GitHub repositories using raw URLs: + +```bash +# Fetch JSON Schema from GitHub and generate models +curl -s https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json | \ + uvx datamodel-codegen --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel + +# Fetch OpenAPI spec from a GitHub repository +curl -s https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json | \ + uvx datamodel-codegen --input-file-type openapi --output-model-type pydantic_v2.BaseModel --output github_api.py +``` + +!!! tip "Using the --url option" + If you have the `http` extra installed, you can use `--url` directly without curl: + + ```bash + uvx --from 'datamodel-code-generator[http]' datamodel-codegen \ + --url https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json \ + --input-file-type jsonschema \ + --output-model-type pydantic_v2.BaseModel + ``` + +### Using with jq for JSON manipulation + +```bash +# Extract a specific schema definition and generate a model +cat openapi.yaml | yq '.components.schemas.User' | \ + uvx datamodel-codegen --input-file-type jsonschema +``` + +--- + +## Comparison: Installation Methods + +| Method | Command | Use Case | +|--------|---------|----------| +| **uvx** | `uvx datamodel-codegen` | One-liner usage, no installation | +| **pipx run** | `pipx run datamodel-code-generator` | One-liner usage, alternative to uvx | +| **pipx install** | `pipx install datamodel-code-generator` | Global installation, frequent usage | +| **uv add** | `uv add datamodel-code-generator` | Project dependency | +| **pip install** | `pip install datamodel-code-generator` | Traditional installation | + +!!! tip "When to use each method" + - **uvx/pipx run**: Quick one-liner generation, testing different versions + - **pipx install**: Frequent CLI usage across multiple projects + - **uv add/pip install**: Project dependency, CI/CD pipelines, programmatic usage + +--- + +# Using datamodel-code-generator as a Module + +Source: https://datamodel-code-generator.koxudaxi.dev/using_as_module/ + +datamodel-code-generator is a CLI tool, but it can also be used as a Python module. + +## ๐Ÿš€ How to Use + +You can generate models with `datamodel_code_generator.generate` using parameters that match the [CLI arguments](./index.md). + +### ๐Ÿ“ฆ Installation + +```bash +pip install 'datamodel-code-generator[http]' +``` + +### ๐Ÿ“ Getting Generated Code as String + +When the `output` parameter is omitted (or set to `None`), `generate()` returns the generated code directly as a string: + +```python +from datamodel_code_generator import InputFileType, generate, GenerateConfig, DataModelType + +json_schema: str = """{ + "type": "object", + "properties": { + "number": {"type": "number"}, + "street_name": {"type": "string"}, + "street_type": {"type": "string", + "enum": ["Street", "Avenue", "Boulevard"] + } + } +}""" + +config = GenerateConfig( + input_file_type=InputFileType.JsonSchema, + input_filename="example.json", + output_model_type=DataModelType.PydanticV2BaseModel, +) +result = generate(json_schema, config=config) +print(result) +``` + +### ๐Ÿ“ Multiple Module Output + +When the schema generates multiple modules, `generate()` returns a `GeneratedModules` dictionary mapping module path tuples to generated code: + +```python +from datamodel_code_generator import InputFileType, generate, GenerateConfig, GeneratedModules + +# Your OpenAPI specification (string, Path, or dict) +openapi_spec: str = "..." # Replace with your actual OpenAPI spec + +# Schema that generates multiple modules (e.g., with $ref to other files) +config = GenerateConfig( + input_file_type=InputFileType.OpenAPI, +) +result: str | GeneratedModules = generate(openapi_spec, config=config) + +if isinstance(result, dict): + for module_path, content in result.items(): + print(f"Module: {'/'.join(module_path)}") + print(content) + print("---") +else: + print(result) +``` + +### ๐Ÿ“ Writing to Files + +To write generated code to the file system, provide a `Path` to the `output` parameter in the config: + +```python +from pathlib import Path +from tempfile import TemporaryDirectory +from datamodel_code_generator import InputFileType, generate, GenerateConfig, DataModelType + +json_schema: str = """{ + "type": "object", + "properties": { + "number": {"type": "number"}, + "street_name": {"type": "string"}, + "street_type": {"type": "string", + "enum": ["Street", "Avenue", "Boulevard"] + } + } +}""" + +with TemporaryDirectory() as temporary_directory_name: + temporary_directory = Path(temporary_directory_name) + output = Path(temporary_directory / 'model.py') + config = GenerateConfig( + input_file_type=InputFileType.JsonSchema, + input_filename="example.json", + output=output, + # set up the output model types + output_model_type=DataModelType.PydanticV2BaseModel, + ) + generate(json_schema, config=config) + model: str = output.read_text() +print(model) +``` + +**โœจ Output:** +```python +# generated by datamodel-codegen: +# filename: example.json +# timestamp: 2020-12-21T08:01:06+00:00 + +from __future__ import annotations + +from enum import Enum +from typing import Optional + +from pydantic import BaseModel + + +class StreetType(Enum): + Street = 'Street' + Avenue = 'Avenue' + Boulevard = 'Boulevard' + + +class Model(BaseModel): + number: Optional[float] = None + street_name: Optional[str] = None + street_type: Optional[StreetType] = None +``` + +--- + +## ๐Ÿ”ง Using the Parser Directly + +You can also call the parser directly for more control. Parser classes also support the `config` parameter similar to `generate()`. + +### Using `config` Parameter (Recommended) + +```python +from datamodel_code_generator import DataModelType, PythonVersion +from datamodel_code_generator.config import JSONSchemaParserConfig +from datamodel_code_generator.model import get_data_model_types +from datamodel_code_generator.parser.jsonschema import JsonSchemaParser + +json_schema: str = """{ + "type": "object", + "properties": { + "number": {"type": "number"}, + "street_name": {"type": "string"}, + "street_type": {"type": "string", + "enum": ["Street", "Avenue", "Boulevard"] + } + } +}""" + +data_model_types = get_data_model_types( + DataModelType.PydanticV2BaseModel, + target_python_version=PythonVersion.PY_311 +) +config = JSONSchemaParserConfig( + data_model_type=data_model_types.data_model, + data_model_root_type=data_model_types.root_model, + data_model_field_type=data_model_types.field_model, + data_type_manager_type=data_model_types.data_type_manager, + dump_resolve_reference_action=data_model_types.dump_resolve_reference_action, +) +parser = JsonSchemaParser(json_schema, config=config) +result = parser.parse() +print(result) +``` + +### Using Keyword Arguments (Backward Compatible) + +```python +from datamodel_code_generator import DataModelType, PythonVersion +from datamodel_code_generator.model import get_data_model_types +from datamodel_code_generator.parser.jsonschema import JsonSchemaParser + +json_schema: str = """{ + "type": "object", + "properties": { + "number": {"type": "number"}, + "street_name": {"type": "string"}, + "street_type": {"type": "string", + "enum": ["Street", "Avenue", "Boulevard"] + } + } +}""" + +data_model_types = get_data_model_types( + DataModelType.PydanticV2BaseModel, + target_python_version=PythonVersion.PY_311 +) +parser = JsonSchemaParser( + json_schema, + data_model_type=data_model_types.data_model, + data_model_root_type=data_model_types.root_model, + data_model_field_type=data_model_types.field_model, + data_type_manager_type=data_model_types.data_type_manager, + dump_resolve_reference_action=data_model_types.dump_resolve_reference_action, +) +result = parser.parse() +print(result) +``` + +### Available Parser Config Classes + +Each parser type has its own config class: + +| Parser | Config Class | +|--------|-------------| +| `JsonSchemaParser` | `JSONSchemaParserConfig` | +| `OpenAPIParser` | `OpenAPIParserConfig` | +| `GraphQLParser` | `GraphQLParserConfig` | + +All config classes inherit from `ParserConfig` and include additional parser-specific options. + +**โœจ Output:** +```python +from __future__ import annotations + +from enum import Enum +from typing import Optional + +from pydantic import BaseModel + + +class StreetType(Enum): + Street = 'Street' + Avenue = 'Avenue' + Boulevard = 'Boulevard' + + +class Model(BaseModel): + number: Optional[float] = None + street_name: Optional[str] = None + street_type: Optional[StreetType] = None + +``` + +--- + +## ๐Ÿ“‹ Return Value Summary + +| `output` Parameter | Single Module | Multiple Modules | +|-------------------|---------------|------------------| +| `None` (default) | `str` | `GeneratedModules` (dict) | +| `Path` (file) | `None` | Error | +| `Path` (directory)| `None` | `None` | + +๐Ÿ“Œ **Note:** When `output` is a file path and multiple modules would be generated, `generate()` raises a `datamodel_code_generator.Error` exception. Use a directory path instead. + +--- + +## ๐Ÿ“– See Also + +- [Dynamic Model Generation](dynamic-model-generation.md) - Generate Python classes at runtime +- [CLI Reference](cli-reference/index.md) - Complete CLI options (same parameters as module) +- [Generate from JSON Schema](jsonschema.md) - JSON Schema examples + +--- + +# Dynamic Model Generation + +Source: https://datamodel-code-generator.koxudaxi.dev/dynamic-model-generation/ + +Generate real Python model classes from JSON Schema or OpenAPI at runtime without writing files. + +## Overview + +While `generate()` produces source code as strings, `generate_dynamic_models()` creates actual Python classes that you can use immediately for validation and data processing. This is useful for: + +- Runtime schema validation without code generation step +- Dynamic API clients that adapt to schema changes +- Testing and prototyping +- Plugin systems with dynamic schemas + +## Quick Start + +```python +from datamodel_code_generator import generate_dynamic_models + +schema = { + "type": "object", + "properties": { + "name": {"type": "string"}, + "age": {"type": "integer"} + }, + "required": ["name"] +} + +models = generate_dynamic_models(schema) +User = models["Model"] + +# Use the model for validation +user = User(name="Alice", age=30) +print(user.model_dump()) # {'name': 'Alice', 'age': 30} + +# Validation errors are raised +try: + User(age="not a number") # Missing required 'name', wrong type for 'age' +except Exception as e: + print(e) +``` + +## API Reference + +### `generate_dynamic_models()` + +```python +def generate_dynamic_models( + input_: Mapping[str, Any], + *, + config: GenerateConfig | None = None, + cache_size: int = 128, +) -> dict[str, type]: +``` + +**Parameters:** + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `input_` | `Mapping[str, Any]` | required | JSON Schema or OpenAPI schema as dict | +| `config` | `GenerateConfig \| None` | `None` | Generation options (same as `generate()`) | +| `cache_size` | `int` | `128` | Maximum cached schemas. Set to `0` to disable | + +**Returns:** `dict[str, type]` - Dictionary mapping class names to model classes. + +### `clear_dynamic_models_cache()` + +```python +def clear_dynamic_models_cache() -> int: +``` + +Clears the internal cache and returns the number of entries cleared. + +## Examples + +### JSON Schema with Nested Models + +```python +from datamodel_code_generator import generate_dynamic_models + +schema = { + "$defs": { + "Address": { + "type": "object", + "properties": { + "street": {"type": "string"}, + "city": {"type": "string"} + }, + "required": ["street", "city"] + }, + "Person": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "address": {"$ref": "#/$defs/Address"} + }, + "required": ["name"] + } + }, + "$ref": "#/$defs/Person" +} + +models = generate_dynamic_models(schema) + +# Both models are available +Person = models["Person"] +Address = models["Address"] + +person = Person( + name="Bob", + address={"street": "123 Main St", "city": "NYC"} +) +print(person.model_dump()) +# {'name': 'Bob', 'address': {'street': '123 Main St', 'city': 'NYC'}} +``` + +### OpenAPI Schema + +OpenAPI schemas are auto-detected: + +```python +from datamodel_code_generator import generate_dynamic_models + +openapi_schema = { + "openapi": "3.0.0", + "info": {"title": "User API", "version": "1.0.0"}, + "paths": {}, + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "id": {"type": "integer"}, + "email": {"type": "string", "format": "email"} + }, + "required": ["id", "email"] + } + } + } +} + +models = generate_dynamic_models(openapi_schema) +User = models["User"] + +user = User(id=1, email="alice@example.com") +``` + +### With Custom Configuration + +```python +from datamodel_code_generator import generate_dynamic_models, GenerateConfig, DataModelType + +schema = {"type": "object", "properties": {"name": {"type": "string"}}} + +config = GenerateConfig( + class_name="Customer", + output_model_type=DataModelType.PydanticV2BaseModel, +) + +models = generate_dynamic_models(schema, config=config) +Customer = models["Customer"] +``` + +### Enum Models + +```python +from datamodel_code_generator import generate_dynamic_models + +schema = { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["pending", "approved", "rejected"] + } + } +} + +models = generate_dynamic_models(schema) +Model = models["Model"] +Status = models["Status"] + +# Enum validation +item = Model(status="approved") +print(item.status) # Status.approved +print(item.status.value) # 'approved' + +# Invalid enum value raises error +try: + Model(status="invalid") +except Exception as e: + print(e) +``` + +### Circular References + +```python +from datamodel_code_generator import generate_dynamic_models + +schema = { + "$defs": { + "Node": { + "type": "object", + "properties": { + "value": {"type": "string"}, + "children": { + "type": "array", + "items": {"$ref": "#/$defs/Node"} + } + } + } + }, + "$ref": "#/$defs/Node" +} + +models = generate_dynamic_models(schema) +Node = models["Node"] + +tree = Node( + value="root", + children=[ + Node(value="child1", children=[]), + Node(value="child2", children=[ + Node(value="grandchild", children=[]) + ]) + ] +) +``` + +## Caching + +Models are cached by schema content and configuration to avoid regeneration: + +```python +from datamodel_code_generator import generate_dynamic_models, clear_dynamic_models_cache + +schema = {"type": "object", "properties": {"x": {"type": "integer"}}} + +# First call generates models +models1 = generate_dynamic_models(schema) + +# Second call returns cached models (same object) +models2 = generate_dynamic_models(schema) +assert models1 is models2 # True + +# Disable caching for specific call +models3 = generate_dynamic_models(schema, cache_size=0) +assert models1 is not models3 # True + +# Clear all cached models +cleared = clear_dynamic_models_cache() +print(f"Cleared {cleared} cached schemas") +``` + +## Thread Safety + +`generate_dynamic_models()` is thread-safe. Multiple threads can safely call it concurrently: + +```python +import threading +from datamodel_code_generator import generate_dynamic_models + +schema = {"type": "object", "properties": {"x": {"type": "integer"}}} +results = [] + +def worker(): + models = generate_dynamic_models(schema) + results.append(models) + +threads = [threading.Thread(target=worker) for _ in range(10)] +for t in threads: + t.start() +for t in threads: + t.join() + +# All threads get the same cached models +assert all(r is results[0] for r in results) +``` + +## Limitations + +| Limitation | Details | +|------------|---------| +| Pydantic v2 only | Pydantic v1 is not supported | +| Not pickle-able | Use `model_dump()` to serialize instances | +| Dict input only | Schema must be a `dict`, not a file path or string | + +## Comparison with `generate()` + +| Feature | `generate()` | `generate_dynamic_models()` | +|---------|-------------|----------------------------| +| Output | Source code string | Actual Python classes | +| Use case | Code generation, file output | Runtime validation | +| Caching | No | Yes (configurable) | +| Thread-safe | Yes | Yes | +| Pydantic v1 | Yes | No | + +## See Also + +- [Using as Module](using_as_module.md) - `generate()` function reference +- [JSON Schema](jsonschema.md) - JSON Schema examples +- [OpenAPI](openapi.md) - OpenAPI examples + +--- + +# pyproject.toml Configuration + +Source: https://datamodel-code-generator.koxudaxi.dev/pyproject_toml/ + + + +# โš™๏ธ pyproject.toml Configuration + +datamodel-code-generator can be configured using `pyproject.toml`. The tool automatically searches for `pyproject.toml` in the current directory and parent directories (stopping at the git repository root). + +## ๐Ÿš€ Basic Usage + +```toml +[tool.datamodel-codegen] +input = "schema.yaml" +output = "models.py" +target-python-version = "3.11" +snake-case-field = true +field-constraints = true +``` + +All CLI options can be used in `pyproject.toml` by converting them to kebab-case (e.g., `--snake-case-field` becomes `snake-case-field`). + +## ๐Ÿ“‹ Named Profiles + +You can define multiple named profiles for different use cases within a single project: + +```toml +[tool.datamodel-codegen] +target-python-version = "3.10" +snake-case-field = true + +[tool.datamodel-codegen.profiles.api] +input = "schemas/api.yaml" +output = "src/models/api.py" +target-python-version = "3.11" + +[tool.datamodel-codegen.profiles.database] +input = "schemas/db.json" +output = "src/models/db.py" +input-file-type = "jsonschema" +``` + +Base settings in `[tool.datamodel-codegen]` are used when no profile is specified, and also serve as defaults for profiles. + +Use a profile with the `--profile` option: + +```bash +datamodel-codegen --profile api +datamodel-codegen --profile database +``` + +## ๐ŸŽฏ Configuration Priority + +Settings are applied in the following priority order (highest to lowest): + +1. **๐Ÿ–ฅ๏ธ CLI arguments** - Always take precedence +2. **๐Ÿ“‹ Profile settings** - From `[tool.datamodel-codegen.profiles.]` +3. **โš™๏ธ Base settings** - From `[tool.datamodel-codegen]` +4. **๐Ÿ”ง Default values** - Built-in defaults + +## ๐Ÿ”€ Merge Rules + +When using profiles, settings are merged using **shallow merge**: + +- Profile values **completely replace** base values (no deep merging) +- Settings not specified in the profile are inherited from the base configuration +- Lists and dictionaries are replaced entirely, not merged + +### ๐Ÿ“ Example + +```toml +[tool.datamodel-codegen] +strict-types = ["str", "int"] +http-headers = ["Authorization: Bearer token"] + +[tool.datamodel-codegen.profiles.api] +strict-types = ["bytes"] +``` + +When using `--profile api`: + +- `strict-types` becomes `["bytes"]` (completely replaces base, not merged) +- `http-headers` is inherited from base as `["Authorization: Bearer token"]` + +## ๐Ÿšซ Ignoring pyproject.toml + +To ignore all `pyproject.toml` configuration and use only CLI arguments: + +```bash +datamodel-codegen --ignore-pyproject --input schema.yaml --output models.py +``` + +## ๐Ÿ”ง Generating Configuration + +Generate a `pyproject.toml` configuration section from CLI arguments: + +```bash +datamodel-codegen --input schema.yaml --output models.py --snake-case-field --generate-pyproject-config +``` + +**โœจ Output:** + +```toml +[tool.datamodel-codegen] +input = "schema.yaml" +output = "models.py" +snake-case-field = true +``` + +Generate CLI command from existing `pyproject.toml`: + +```bash +datamodel-codegen --generate-cli-command +``` + +With a specific profile: + +```bash +datamodel-codegen --profile api --generate-cli-command +``` + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--ignore-pyproject`](cli-reference/general-options.md#ignore-pyproject) - Ignore pyproject.toml configuration +- ๐Ÿ”ง [CLI Reference: `--generate-pyproject-config`](cli-reference/general-options.md#generate-pyproject-config) - Generate pyproject.toml from CLI arguments +- ๐Ÿ–ฅ๏ธ [CLI Reference: `--generate-cli-command`](cli-reference/general-options.md#generate-cli-command) - Generate CLI command from pyproject.toml + +--- + +# CI/CD Integration + +Source: https://datamodel-code-generator.koxudaxi.dev/ci-cd/ + + + +# CI/CD Integration + +This guide covers how to use datamodel-code-generator in CI/CD pipelines and development workflows to ensure generated code stays in sync with schemas. + +!!! note + The package name is `datamodel-code-generator`, and the CLI command is `datamodel-codegen`. + +--- + +## Official GitHub Action + +The official GitHub Action provides a simple way to validate generated models in your CI pipeline. + +### Basic Usage + +```yaml +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schema.yaml + output: src/models.py + input-file-type: openapi + output-model-type: pydantic_v2.BaseModel +``` + +By default, the action runs in **check mode** (`--check`), which validates that the existing output file matches what would be generated. If they differ, the action fails. + +### Inputs + +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `input` | Yes | - | Input schema file or directory | +| `output` | Yes | - | Output file or directory | +| `input-file-type` | Yes | - | Input file type (`openapi`, `jsonschema`, `json`, `yaml`, `csv`, `graphql`) | +| `output-model-type` | Yes | - | Output model type (`pydantic_v2.BaseModel`, `pydantic.BaseModel`, `dataclasses.dataclass`, `typing.TypedDict`, `msgspec.Struct`) | +| `check` | No | `true` | Validate that existing output is up to date (no generation) | +| `working-directory` | No | `.` | Working directory (where `pyproject.toml` is located) | +| `profile` | No | - | Named profile from `pyproject.toml` | +| `extra-args` | No | - | Additional CLI arguments | +| `version` | No | - | Specific version to install (defaults to action's tag version) | +| `extras` | No | - | Optional extras to install (comma-separated: `graphql`, `http`, `validation`, `ruff`, `all`) | + +### Example: Validate on Pull Request + +```yaml title=".github/workflows/validate-models.yml" +name: Validate Generated Models + +on: + pull_request: + paths: + - 'schemas/**' + - 'src/models/**' + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schemas/api.yaml + output: src/models/api.py + input-file-type: openapi + output-model-type: pydantic_v2.BaseModel +``` + +### Example: Monorepo with Multiple Schemas + +```yaml title=".github/workflows/validate-models.yml" +jobs: + validate: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - working-directory: packages/api + input: schemas/openapi.yaml + output: src/models.py + input-file-type: openapi + - working-directory: packages/admin + input: schemas/schema.json + output: src/models.py + input-file-type: jsonschema + steps: + - uses: actions/checkout@v4 + + - uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: ${{ matrix.input }} + output: ${{ matrix.output }} + input-file-type: ${{ matrix.input-file-type }} + output-model-type: pydantic_v2.BaseModel + working-directory: ${{ matrix.working-directory }} +``` + +### Example: Using Profiles + +```yaml +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schemas/api.yaml + output: src/models.py + input-file-type: openapi + output-model-type: pydantic_v2.BaseModel + profile: api +``` + +### Example: Generate Models (Instead of Validation) + +Set `check: 'false'` to actually generate the models: + +```yaml +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schema.yaml + output: src/models.py + input-file-type: openapi + output-model-type: pydantic_v2.BaseModel + check: 'false' +``` + +### Example: GraphQL Schema + +For GraphQL schemas, use the `extras` input to install the required dependency: + +```yaml +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schema.graphql + output: src/models.py + input-file-type: graphql + output-model-type: pydantic_v2.BaseModel + extras: 'graphql' +``` + +### Example: Multiple Extras + +You can install multiple extras with comma-separated values: + +```yaml +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schema.yaml + output: src/models.py + input-file-type: openapi + output-model-type: pydantic_v2.BaseModel + extras: 'http,validation,ruff' +``` + +### Example: Additional CLI Options + +Use `extra-args` for CLI options not covered by the inputs: + +```yaml +- uses: koxudaxi/datamodel-code-generator@0.44.0 + with: + input: schema.yaml + output: src/models.py + input-file-type: openapi + output-model-type: pydantic_v2.BaseModel + extra-args: '--snake-case-field --field-constraints' +``` + +!!! tip "Version Pinning" + Always pin the action to a specific version tag (e.g., `@0.44.0`) to ensure reproducible builds. The action installs the same version of `datamodel-code-generator` as the tag. + +--- + +## The `--check` Flag + +The `--check` flag verifies that generated code matches existing files without modifying them. If the output would differ, it exits with a non-zero status code. + +```bash +datamodel-codegen --check +``` + +### Success (Exit code 0) + +When generated code matches the existing file, the command exits silently with code 0: + +```console +$ datamodel-codegen --check +$ echo $? +0 +``` + +### Failure (Exit code 1) + +When the schema has changed and the generated code would differ, a unified diff is shown and the command exits with code 1: + +```console +$ datamodel-codegen --check +--- models.py ++++ models.py (expected) +@@ -12,3 +12,4 @@ + name: Optional[str] = None + age: Optional[int] = None + email: Optional[str] = None ++ active: Optional[bool] = None +$ echo $? +1 +``` + +!!! tip "Best Practice: Use pyproject.toml" + Instead of passing many CLI options, configure all settings in `pyproject.toml`. This keeps CI commands simple, ensures consistency between local development and CI, and makes configuration easier to maintain. + + ```toml title="pyproject.toml" + [tool.datamodel-codegen] + input = "schemas/api.yaml" + output = "src/models/api.py" + output-model-type = "pydantic_v2.BaseModel" + disable-timestamp = true + ``` + + Then simply run: + + ```bash + datamodel-codegen --check + ``` + + For projects with multiple schemas, use [named profiles](pyproject_toml.md#named-profiles) to organize configurations by purpose. + +**Related:** [`--check`](cli-reference/general-options.md#check), [`--disable-timestamp`](cli-reference/template-customization.md#disable-timestamp), [pyproject.toml Configuration](pyproject_toml.md) + +--- + +## GitHub Actions + +### Basic Example + +```yaml title=".github/workflows/ci.yml" +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + check-generated-code: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Install dependencies + run: pip install datamodel-code-generator + + - name: Verify generated models are up-to-date + run: datamodel-codegen --check +``` + +### Using Profiles for Multiple Schemas + +For projects with multiple schemas, use [named profiles](pyproject_toml.md#named-profiles) to organize configurations by purpose: + +```toml title="pyproject.toml" +[tool.datamodel-codegen] +output-model-type = "pydantic_v2.BaseModel" +disable-timestamp = true + +[tool.datamodel-codegen.profiles.api] +input = "schemas/openapi/api.yaml" +output = "src/models/api.py" + +[tool.datamodel-codegen.profiles.events] +input = "schemas/jsonschema/events.json" +output = "src/models/events.py" +input-file-type = "jsonschema" +``` + +```yaml title=".github/workflows/ci.yml" +- name: Verify API models are up-to-date + run: datamodel-codegen --profile api --check + +- name: Verify event models are up-to-date + run: datamodel-codegen --profile events --check +``` + +### Using uv + +If your project uses [uv](https://github.com/astral-sh/uv), you can run the CLI via `uv run`. This example installs the tool ephemerally (no need to add it to your project dependencies): + +```yaml title=".github/workflows/ci.yml" +- name: Install uv + uses: astral-sh/setup-uv@v4 + +- name: Verify generated models are up-to-date + run: uv run --with datamodel-code-generator datamodel-codegen --profile api --check +``` + +--- + +## Pre-commit Hook + +You can use datamodel-code-generator as a [pre-commit](https://pre-commit.com/) hook to automatically check or regenerate models before commits. + +!!! tip + Pin `rev` to a released tag (e.g., `vX.Y.Z`) to keep generated output stable and reproducible across developer machines and CI. + +### With pyproject.toml (Recommended) + +Configure settings in `pyproject.toml` and use a simple pre-commit hook: + +```yaml title=".pre-commit-config.yaml" +repos: + - repo: https://github.com/koxudaxi/datamodel-code-generator + rev: vX.Y.Z + hooks: + - id: datamodel-code-generator + args: [--check] + files: ^schemas/ +``` + +### With Profiles + +For projects with multiple schemas using [named profiles](pyproject_toml.md#named-profiles): + +```yaml title=".pre-commit-config.yaml" +repos: + - repo: https://github.com/koxudaxi/datamodel-code-generator + rev: vX.Y.Z + hooks: + - id: datamodel-code-generator + name: Check API models + args: [--profile, api, --check] + files: ^schemas/openapi/ + - id: datamodel-code-generator + name: Check event models + args: [--profile, events, --check] + files: ^schemas/jsonschema/ +``` + +### Auto-regenerate Mode + +This configuration automatically regenerates models when schema files change: + +```yaml title=".pre-commit-config.yaml" +repos: + - repo: https://github.com/koxudaxi/datamodel-code-generator + rev: vX.Y.Z + hooks: + - id: datamodel-code-generator + files: ^schemas/ +``` + +!!! note "Installing the hook" + Ensure `pre-commit` is installed, then install the hooks: + + ```bash + pip install pre-commit + pre-commit install + ``` + +--- + +## GitLab CI + +```yaml title=".gitlab-ci.yml" +check-generated-code: + image: python:3.14 + script: + - pip install datamodel-code-generator + - datamodel-codegen --check + rules: + - changes: + - schemas/**/* + - src/models/**/* +``` + +--- + +## Makefile Integration + +Add targets to your Makefile for easy generation and checking: + +```makefile title="Makefile" +.PHONY: generate-models check-models + +generate-models: + datamodel-codegen + +check-models: + datamodel-codegen --check +``` + +Then use in CI: + +```yaml title=".github/workflows/ci.yml" +- name: Check generated models + run: make check-models +``` + +For projects with multiple profiles: + +```makefile title="Makefile" +.PHONY: generate-all check-all + +generate-all: + datamodel-codegen --profile api + datamodel-codegen --profile events + +check-all: + datamodel-codegen --profile api --check + datamodel-codegen --profile events --check +``` + +--- + +## Troubleshooting + +### Check fails due to formatting differences + +Ensure you're using the same formatters in CI as locally. Configure formatters in `pyproject.toml`: + +```toml title="pyproject.toml" +[tool.datamodel-codegen] +formatters = ["ruff"] +``` + +See [Formatting](formatting.md) for details. + +**Related:** [`--formatters`](cli-reference/template-customization.md#formatters) + +### Check fails due to timestamp + +Always use `disable-timestamp = true` in `pyproject.toml`: + +```toml title="pyproject.toml" +[tool.datamodel-codegen] +disable-timestamp = true +``` + +**Related:** [`--disable-timestamp`](cli-reference/template-customization.md#disable-timestamp) + +### Different Python versions produce different output + +Some type annotations differ between Python versions. Pin the target version in `pyproject.toml` and ensure CI uses the same Python version as development: + +```toml title="pyproject.toml" +[tool.datamodel-codegen] +target-python-version = "3.14" +``` + +**Related:** [`--target-python-version`](cli-reference/model-customization.md#target-python-version) + +--- + +# LLM Integration + +Source: https://datamodel-code-generator.koxudaxi.dev/llm-integration/ + + + +The `--generate-prompt` option generates a formatted prompt that you can use +to consult Large Language Models (LLMs) about datamodel-code-generator CLI options. + +## Overview + +When you're unsure which CLI options to use for your specific use case, +you can generate a prompt containing all available options and their descriptions, +then ask an LLM for recommendations. + +```bash +datamodel-codegen --generate-prompt "How do I generate strict Pydantic v2 models?" +``` + +The generated prompt includes: + +- Your question (if provided) +- Current CLI options you've specified +- All options organized by category with descriptions +- Full help text for reference + +## CLI LLM Tools + +Pipe the generated prompt directly to CLI-based LLM tools: + +### Claude Code + +[Claude Code](https://docs.anthropic.com/en/docs/claude-code) is Anthropic's official CLI tool. +Use `-p` flag for non-interactive (pipe) mode: + +```bash +datamodel-codegen --generate-prompt "Best options for API response models?" | claude -p +``` + +### OpenAI Codex CLI + +[Codex CLI](https://github.com/openai/codex) is OpenAI's CLI tool. +Use `exec` subcommand for non-interactive mode: + +```bash +datamodel-codegen --generate-prompt "How to handle nullable fields?" | codex exec +``` + +### Other CLI Tools + +Other popular LLM CLI tools that accept stdin: + +| Tool | Command | Repository | +|------|---------|------------| +| llm | `\| llm` | [simonw/llm](https://github.com/simonw/llm) | +| aichat | `\| aichat` | [sigoden/aichat](https://github.com/sigoden/aichat) | +| sgpt | `\| sgpt` | [TheR1D/shell_gpt](https://github.com/TheR1D/shell_gpt) | +| mods | `\| mods` | [charmbracelet/mods](https://github.com/charmbracelet/mods) | + +Check each tool's documentation for specific usage and options. + +## Web LLM Chat Services + +Copy the prompt to clipboard, then paste into your preferred web-based LLM chat: + +### macOS + +```bash +datamodel-codegen --generate-prompt | pbcopy +``` + +### Linux (X11) + +```bash +datamodel-codegen --generate-prompt | xclip -selection clipboard +``` + +### Linux (Wayland) + +```bash +datamodel-codegen --generate-prompt | wl-copy +``` + +### Windows (PowerShell) + +```powershell +datamodel-codegen --generate-prompt | Set-Clipboard +``` + +### WSL2 + +```bash +datamodel-codegen --generate-prompt | clip.exe +``` + +## Usage Examples + +### Basic Usage + +Generate a prompt without a specific question: + +```bash +datamodel-codegen --generate-prompt +``` + +### With a Question + +Include your specific question in the prompt: + +```bash +datamodel-codegen --generate-prompt "What options should I use for GraphQL schema?" +``` + +### With Current Options + +Show your current configuration and ask for improvements: + +```bash +datamodel-codegen \ + --input schema.json \ + --output-model-type pydantic_v2.BaseModel \ + --use-annotated \ + --generate-prompt "Are there any other options I should consider?" +``` + +### Pipe to Claude with Options + +```bash +datamodel-codegen \ + --input openapi.yaml \ + --output-model-type dataclasses.dataclass \ + --generate-prompt "How can I add JSON serialization support?" \ + | claude -p +``` + +## Tips + +1. **Be specific** - Include a clear question to get more relevant recommendations +2. **Show context** - Add your current options so the LLM understands your setup +3. **Iterate** - Use the suggestions, then ask follow-up questions if needed + +--- + +# Frequently Asked Questions + +Source: https://datamodel-code-generator.koxudaxi.dev/faq/ + +## ๐Ÿ“‹ Schema Handling + +### ๐Ÿ”€ oneOf/anyOf generates unexpected Union types + +When using `oneOf` or `anyOf`, the generated models may not match your expectations. Use `--union-mode` to control how unions are generated: + +```bash +# Smart union (Pydantic v2 only) - validates against types in order +datamodel-codegen --union-mode smart --output-model-type pydantic_v2.BaseModel ... + +# Left-to-right validation +datamodel-codegen --union-mode left_to_right ... +``` + +See [CLI Reference: `--union-mode`](cli-reference/model-customization.md#union-mode) for details. + +### ๐Ÿ”— allOf doesn't merge properties as expected + +Control how `allOf` schemas merge fields: + +```bash +# Merge only constraints (minItems, maxItems, pattern, etc.) - default +datamodel-codegen --allof-merge-mode constraints ... + +# Merge constraints + annotations (default, examples) +datamodel-codegen --allof-merge-mode all ... + +# Don't merge any fields +datamodel-codegen --allof-merge-mode none ... +``` + +See [CLI Reference: `--allof-merge-mode`](cli-reference/typing-customization.md#allof-merge-mode) for details. + +๐Ÿ“Ž Related: [#399](https://github.com/koxudaxi/datamodel-code-generator/issues/399) + +### ๐Ÿ“ How to generate from multiple schema files? + +Use a directory as input, or use `$ref` to reference other files: + +```bash +# Generate from directory containing multiple schemas +datamodel-codegen --input schemas/ --output models/ +``` + +For schemas with cross-file `$ref`, ensure you have the HTTP extra for remote refs: + +```bash +pip install 'datamodel-code-generator[http]' +``` + +๐Ÿ“Ž Related: [#215](https://github.com/koxudaxi/datamodel-code-generator/issues/215) + +### ๐Ÿ”ค YAML bool keywords (YES, NO, true, false) in string enums + +YAML 1.1 treats unquoted keywords like `YES`, `NO`, `on`, `off`, `true`, `false` as boolean values. This tool preserves them as strings to avoid unexpected conversions in schema contexts: + +```yaml +# Input YAML +enum: + - YES + - NO + - NOT_APPLICABLE +``` + +```python +# Generated code (strings preserved) +class MyEnum(Enum): + YES = 'YES' + NO = 'NO' + NOT_APPLICABLE = 'NOT_APPLICABLE' +``` + +This matches the expected behavior when `type: string` is specified in your schema. If you need the previous behavior where YAML bool keywords were converted to Python booleans, please [open an issue](https://github.com/koxudaxi/datamodel-code-generator/issues) describing your use case. + +๐Ÿ“Ž Related: [#1653](https://github.com/koxudaxi/datamodel-code-generator/issues/1653), [#1766](https://github.com/koxudaxi/datamodel-code-generator/issues/1766), [#2338](https://github.com/koxudaxi/datamodel-code-generator/issues/2338) + +--- + +## ๐Ÿ” Type Checking + +### โš ๏ธ mypy complains about Field constraints + +If mypy reports errors about `conint`, `constr`, or other constrained types, use `--field-constraints` or `--use-annotated`: + +```bash +# Use Field(..., ge=0) instead of conint(ge=0) +datamodel-codegen --field-constraints ... + +# Use Annotated[int, Field(ge=0)] +datamodel-codegen --use-annotated ... +``` + +See [Field Constraints](field-constraints.md) for more information. + +### ๐Ÿค” Type checker doesn't understand generated types + +Ensure you're using the correct target Python version: + +```bash +datamodel-codegen --target-python-version 3.11 ... +``` + +This affects type syntax generation (e.g., `list[str]` vs `List[str]`, `X | Y` vs `Union[X, Y]`). + +--- + +## ๐Ÿท๏ธ Field Naming + +### ๐Ÿšซ Property names conflict with Python reserved words + +Properties like `class`, `from`, `import` are automatically renamed with a `field_` prefix. Control this behavior: + +```bash +# Custom prefix (default: "field") +datamodel-codegen --special-field-name-prefix my_prefix ... + +# Remove special prefix entirely +datamodel-codegen --remove-special-field-name-prefix ... +``` + +### ๐Ÿ”ฃ Field names have special characters + +JSON/YAML property names with spaces, dashes, or special characters are converted to valid Python identifiers. An alias is automatically generated to preserve the original name: + +```python +class Model(BaseModel): + my_field: str = Field(..., alias='my-field') +``` + +To disable aliases: + +```bash +datamodel-codegen --no-alias ... +``` + +See [Field Aliases](aliases.md) for custom alias mappings. + +### ๐Ÿ Want snake_case field names from camelCase + +```bash +datamodel-codegen --snake-case-field ... +``` + +This generates snake_case field names with camelCase aliases: + +```python +class User(BaseModel): + first_name: str = Field(..., alias='firstName') +``` + +--- + +## ๐Ÿ”„ Output Stability + +### โฐ Generated output changes on every run + +The timestamp in the header changes on each run. Disable it for reproducible output: + +```bash +datamodel-codegen --disable-timestamp ... +``` + +### ๐ŸŒ Output differs between environments + +Ensure consistent formatting across environments: + +```bash +# Explicitly set formatters +datamodel-codegen --formatters black isort ... + +# Or disable formatting entirely for raw output +datamodel-codegen --formatters ... +``` + +Also ensure the same Python version and formatter configurations (`pyproject.toml`) are used. + +### ๐Ÿค– CI fails because generated code is different + +Use `--check` mode in CI to verify generated files are up-to-date: + +```bash +datamodel-codegen --check --input schema.yaml --output models.py +``` + +This exits with code 1 if the output would differ, without modifying files. + +--- + +## โšก Performance + +### ๐Ÿข Generation is slow for large schemas + +For very large schemas with many models: + +1. Use `--reuse-model` to deduplicate identical models +2. Consider splitting schemas into multiple files +3. Use `--disable-warnings` to reduce output + +```bash +datamodel-codegen --reuse-model --disable-warnings ... +``` + +See [Model Reuse and Deduplication](model-reuse.md) for details. + +--- + +## ๐Ÿ”ง Output Model Types + +### ๐Ÿคท Which output model type should I use? + +- **Pydantic v2** (`pydantic_v2.BaseModel`): โœจ Recommended for new projects. Better performance and modern API. +- **Pydantic v1** (`pydantic.BaseModel`): ๐Ÿ”„ Default for backward compatibility with existing codebases. +- **dataclasses**: Simple data containers without validation. +- **TypedDict**: Type hints for dict structures. +- **msgspec**: High-performance serialization. + +See [Output Model Types](what_is_the_difference_between_v1_and_v2.md) for a detailed comparison. + +```bash +# For new projects +datamodel-codegen --output-model-type pydantic_v2.BaseModel ... +``` + +See [Pydantic v1 vs v2](what_is_the_difference_between_v1_and_v2.md) for migration details. + +๐Ÿ“Ž Related: [#803](https://github.com/koxudaxi/datamodel-code-generator/issues/803) + +### ๐Ÿ’ฅ Generated code doesn't work with my Pydantic version + +Ensure the output model type matches your installed Pydantic version: + +```bash +# Check your Pydantic version +python -c "import pydantic; print(pydantic.VERSION)" + +# Generate for Pydantic v2 +datamodel-codegen --output-model-type pydantic_v2.BaseModel ... + +# Generate for Pydantic v1 +datamodel-codegen --output-model-type pydantic.BaseModel ... +``` + +--- + +## ๐ŸŒ Remote Schemas + +### ๐Ÿ“ก Cannot fetch schema from URL + +Install the HTTP extra: + +```bash +pip install 'datamodel-code-generator[http]' +``` + +For authenticated endpoints: + +```bash +datamodel-codegen --url https://api.example.com/schema.yaml \ + --http-headers "Authorization: Bearer TOKEN" \ + --output model.py +``` + +### ๐Ÿ”’ SSL certificate errors + +For development/testing with self-signed certificates: + +```bash +datamodel-codegen --url https://... --http-ignore-tls --output model.py +``` + +!!! warning "โš ๏ธ Security Notice" + Only use `--http-ignore-tls` in trusted environments. + +--- + +## ๐Ÿ“˜ OpenAPI Specific + +### ๐Ÿ“ How to handle readOnly/writeOnly properties? + +Use `--read-only-write-only-model-type` to generate separate Request/Response models: + +```bash +# Generate Request/Response models only +datamodel-codegen --read-only-write-only-model-type request-response ... + +# Generate Base + Request + Response models +datamodel-codegen --read-only-write-only-model-type all ... +``` + +๐Ÿ“Ž Related: [#727](https://github.com/koxudaxi/datamodel-code-generator/issues/727) + +### โ“ Why are nullable fields not Optional? + +Use `--strict-nullable` to treat nullable fields as truly optional: + +```bash +datamodel-codegen --strict-nullable ... +``` + +๐Ÿ“Ž Related: [#327](https://github.com/koxudaxi/datamodel-code-generator/issues/327) + +--- + +## ๐Ÿ”ง Advanced + +### ๐Ÿ“ฆ How to use TypeAlias instead of RootModel? + +Use `--use-type-alias` (experimental) to generate type aliases instead of root models: + +```bash +datamodel-codegen --use-type-alias --output-model-type pydantic_v2.BaseModel ... +``` + +See [Root Models and Type Aliases](root-model-and-type-alias.md) for details. + +๐Ÿ“Ž Related: [#2505](https://github.com/koxudaxi/datamodel-code-generator/issues/2505) + +--- + +## ๐Ÿ“– See Also + +- ๐Ÿ–ฅ๏ธ [CLI Reference](cli-reference/index.md) - Complete option documentation +- โš™๏ธ [pyproject.toml Configuration](pyproject_toml.md) - Configure options via file +- ๐Ÿ› [GitHub Issues](https://github.com/koxudaxi/datamodel-code-generator/issues) - Report bugs or request features +- ๐Ÿ’ฌ [Discussions](https://github.com/koxudaxi/datamodel-code-generator/discussions) - Ask questions and share ideas + +--- + +# Development + +Source: https://datamodel-code-generator.koxudaxi.dev/development-contributing/ + +Install the package in editable mode: + +```sh +$ git clone git@github.com:koxudaxi/datamodel-code-generator.git +$ pip install -e datamodel-code-generator +``` + +# ๐Ÿค Contribute + +We are waiting for your contributions to `datamodel-code-generator`. + +## ๐Ÿ“ How to contribute + +```bash +## 1. Clone your fork repository +$ git clone git@github.com:/datamodel-code-generator.git +$ cd datamodel-code-generator + +## 2. Install [uv](https://docs.astral.sh/uv/getting-started/installation/) +$ curl -LsSf https://astral.sh/uv/install.sh | sh + +## 3. Install tox with uv +$ uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv + +## 4. Create developer environment +$ tox run -e dev + +.tox/dev is a Python environment you can use for development purposes + +## 5. Install pre-commit hooks +$ uv tool install prek +$ prek install + +## 6. Create new branch and rewrite code. +$ git checkout -b new-branch + +## 7. Run unittest under Python 3.13 (you should pass all test and coverage should be 100%) +$ tox run -e 3.13 + +## 8. Format and lint code (will print errors that cannot be automatically fixed) +$ tox run -e fix + +## 9. Check README help text is up to date +$ tox run -e readme + +## 10. Check CLI documentation is up to date +$ tox run -e cli-docs + +## 11. Commit and Push... +``` + +## โž• Adding a New CLI Option + +When adding a new CLI option to `datamodel-code-generator`, follow these steps: + +### Step 1: Implement the option (Required) + +Add the option to `src/datamodel_code_generator/arguments.py`: + +```python +arg_parser.add_argument( + "--my-new-option", + help="Description of what this option does", + action="store_true", # or other action type +) +``` + +### Step 2: Add a test with documentation marker (Required) + +Create a test that demonstrates the option and add the `@pytest.mark.cli_doc()` marker: + +```python +@pytest.mark.cli_doc( + options=["--my-new-option"], + input_schema="jsonschema/example.json", # Path relative to tests/data/ + cli_args=["--my-new-option"], + golden_output="jsonschema/example_with_my_option.py", # Expected output +) +def test_my_new_option(output_file: Path) -> None: + """Short description of what the option does. + + This docstring becomes the documentation for the option. + Explain when and why users would use this option. + """ + run_main_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "example.json", + output_path=output_file, + extra_args=["--my-new-option"], + ... + ) +``` + +### Step 3: Categorize the option (Optional) + +By default, new options appear in "General Options". To place in a specific category, add to `src/datamodel_code_generator/cli_options.py`: + +```python +CLI_OPTION_META: dict[str, CLIOptionMeta] = { + ... + "--my-new-option": CLIOptionMeta( + name="--my-new-option", + category=OptionCategory.MODEL, # or FIELD, TYPING, TEMPLATE, etc. + ), +} +``` + +### Step 4: Generate and verify documentation + +```bash +# Regenerate CLI docs +$ pytest --collect-cli-docs -p no:xdist -q +$ python scripts/build_cli_docs.py + +# Verify docs are correct +$ tox run -e cli-docs + +# If you modified config.py, regenerate config TypedDicts +$ tox run -e config-types +``` + +### ๐Ÿ”ง Troubleshooting + +If `tox run -e cli-docs` fails: + +- **"No test found documenting option --xxx"**: Add `@pytest.mark.cli_doc(options=["--xxx"], ...)` to a test +- **"File not found: ..."**: Check that `input_schema` and `golden_output` paths are correct +- **"CLI docs are OUT OF DATE"**: Run `python scripts/build_cli_docs.py` to regenerate + +## ๐Ÿ“– CLI Documentation Marker Reference + +The `cli_doc` marker supports: + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `options` | Yes | List of CLI options this test documents | +| `input_schema` | Yes | Input schema path (relative to `tests/data/`) | +| `cli_args` | Yes | CLI arguments used in the test | +| `golden_output` | Yes* | Expected output file path | +| `model_outputs` | No | Dict of model type โ†’ output file (for multi-model tabs) | +| `version_outputs` | No | Dict of Python version โ†’ output file | +| `comparison_output` | No | Baseline output without option (for before/after) | +| `primary` | No | Set `True` if this is the main example for the option | + +*Either `golden_output` or `model_outputs` is required. + +See existing tests in `tests/main/` for examples. + +--- diff --git a/docs/llms.txt b/docs/llms.txt new file mode 100644 index 000000000..7839e2594 --- /dev/null +++ b/docs/llms.txt @@ -0,0 +1,73 @@ +# datamodel-code-generator + +> This code generator creates pydantic model from an openapi file and others. + +- [datamodel-code-generator](https://datamodel-code-generator.koxudaxi.dev/): Generate Python data models from schema definitions in seconds. +## CLI Reference + +- [CLI Reference](https://datamodel-code-generator.koxudaxi.dev/cli-reference/): This documentation is auto-generated from test cases. +- [Base Options](https://datamodel-code-generator.koxudaxi.dev/cli-reference/base-options/) +- [Model Customization](https://datamodel-code-generator.koxudaxi.dev/cli-reference/model-customization/) +- [Field Customization](https://datamodel-code-generator.koxudaxi.dev/cli-reference/field-customization/) +- [Typing Customization](https://datamodel-code-generator.koxudaxi.dev/cli-reference/typing-customization/) +- [Template Customization](https://datamodel-code-generator.koxudaxi.dev/cli-reference/template-customization/) +- [OpenAPI-only Options](https://datamodel-code-generator.koxudaxi.dev/cli-reference/openapi-only-options/) +- [GraphQL-only Options](https://datamodel-code-generator.koxudaxi.dev/cli-reference/graphql-only-options/) +- [General Options](https://datamodel-code-generator.koxudaxi.dev/cli-reference/general-options/) +- [Utility Options](https://datamodel-code-generator.koxudaxi.dev/cli-reference/utility-options/) +- [Quick Reference](https://datamodel-code-generator.koxudaxi.dev/cli-reference/quick-reference/): All CLI options in one page for easy **Ctrl+F** searching. +### Manual + +- [Help](https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/help/) +- [Version](https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/version/) +- [Debug](https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/debug/) +- [Profile](https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/profile/) +- [No Color](https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/no-color/) +- [Generate Prompt](https://datamodel-code-generator.koxudaxi.dev/cli-reference/manual/generate-prompt/) + + +- [Supported Input Formats](https://datamodel-code-generator.koxudaxi.dev/supported-data-types/): This code generator supports the following input formats: +## Usage + +### Input Formats + +- [Generate from OpenAPI](https://datamodel-code-generator.koxudaxi.dev/openapi/): Generate Pydantic models from OpenAPI 3 schema definitions. +- [Generate from JSON Schema](https://datamodel-code-generator.koxudaxi.dev/jsonschema/): Generate Pydantic models from JSON Schema definitions. See [Supported Data Types](./supported-data-types.md#openapi-3-and-json-schema) for supporte... +- [Generate from JSON Data](https://datamodel-code-generator.koxudaxi.dev/jsondata/): Generate Pydantic models directly from JSON data. Under the hood, the generator uses [GenSON](https://pypi.org/project/genson/) to infer a JSON Sch... +- [Generate from GraphQL](https://datamodel-code-generator.koxudaxi.dev/graphql/): Generate Pydantic models from GraphQL schema definitions. +- [Generate from Python Models {#python-model}](https://datamodel-code-generator.koxudaxi.dev/python-model/): Generate code from existing Python types: Pydantic models, dataclasses, TypedDict, or dict schemas. This is useful for converting between model typ... + +### Output Customization + +- [Output Model Types](https://datamodel-code-generator.koxudaxi.dev/what_is_the_difference_between_v1_and_v2/): datamodel-code-generator supports multiple output model types. This page compares them to help you choose the right one for your project. +- [Model Reuse and Deduplication](https://datamodel-code-generator.koxudaxi.dev/model-reuse/): When generating models from schemas, you may encounter duplicate model definitions. datamodel-code-generator provides options to deduplicate models... +- [Module Structure and Exports](https://datamodel-code-generator.koxudaxi.dev/module-exports/): When generating models to a directory structure, datamodel-code-generator can automatically create `__init__.py` files with `__all__` exports. This... +- [Type Mappings and Custom Types](https://datamodel-code-generator.koxudaxi.dev/type-mappings/): datamodel-code-generator allows you to customize how schema types are mapped to Python types. This is essential for projects with specific type req... +- [Python Version Compatibility](https://datamodel-code-generator.koxudaxi.dev/python-version-compatibility/): datamodel-code-generator can generate code compatible with different Python versions. This page explains how to control type annotation syntax and ... +- [Root Models and Type Aliases](https://datamodel-code-generator.koxudaxi.dev/root-model-and-type-alias/): When a schema defines a simple type (not an object with properties), `datamodel-code-generator` creates a root model. If you don't want to introduc... +- [Field Constraints](https://datamodel-code-generator.koxudaxi.dev/field-constraints/): The `--field-constraints` option converts all `con*` annotations (like `conint`, `constr`) to `Field` constraint options. +- [Field Aliases](https://datamodel-code-generator.koxudaxi.dev/aliases/): The `--aliases` option allows you to rename fields in the generated models. This is useful when you want to use different Python field names than t... +- [Field Validators](https://datamodel-code-generator.koxudaxi.dev/validators/): The `--validators` option allows you to add custom field validators to generated Pydantic v2 models. This enables you to inject validation logic in... +- [Custom Class Decorators](https://datamodel-code-generator.koxudaxi.dev/class-decorators/): The `--class-decorators` option adds custom decorators to all generated model classes. This is useful for integrating with serialization libraries ... +- [OpenAPI-Specific Options](https://datamodel-code-generator.koxudaxi.dev/openapi-options/): When working with OpenAPI specifications, datamodel-code-generator provides several options to control how schemas, operations, and special propert... + +### Templates and Formatting + +- [Custom Templates](https://datamodel-code-generator.koxudaxi.dev/custom_template/): One of the powerful features of datamodel-code-generator is the ability to use custom templates with the `--custom-template-dir` option. This allow... +- [Custom Code Formatters](https://datamodel-code-generator.koxudaxi.dev/custom-formatters/): Create your own custom code formatters for specialized formatting needs. +- [Code Formatting](https://datamodel-code-generator.koxudaxi.dev/formatting/): Generated code is automatically formatted using code formatters. By default, `black` and `isort` are used to produce consistent, well-formatted out... + +### Integration + +- [One-liner Usage](https://datamodel-code-generator.koxudaxi.dev/oneliner/): This guide covers how to use datamodel-code-generator with pipes and clipboard tools for quick, one-time code generation without permanent installa... +- [Using datamodel-code-generator as a Module](https://datamodel-code-generator.koxudaxi.dev/using_as_module/): datamodel-code-generator is a CLI tool, but it can also be used as a Python module. +- [Dynamic Model Generation](https://datamodel-code-generator.koxudaxi.dev/dynamic-model-generation/): Generate real Python model classes from JSON Schema or OpenAPI at runtime without writing files. +- [pyproject.toml Configuration](https://datamodel-code-generator.koxudaxi.dev/pyproject_toml/): datamodel-code-generator can be configured using `pyproject.toml`. The tool automatically searches for `pyproject.toml` in the current directory an... +- [CI/CD Integration](https://datamodel-code-generator.koxudaxi.dev/ci-cd/): This guide covers how to use datamodel-code-generator in CI/CD pipelines and development workflows to ensure generated code stays in sync with sche... +- [LLM Integration](https://datamodel-code-generator.koxudaxi.dev/llm-integration/): The `--generate-prompt` option generates a formatted prompt that you can use to consult Large Language Models (LLMs) about datamodel-code-generator... + + +## Optional + +- [Frequently Asked Questions](https://datamodel-code-generator.koxudaxi.dev/faq/) +- [Development](https://datamodel-code-generator.koxudaxi.dev/development-contributing/): Install the package in editable mode: diff --git a/pyproject.toml b/pyproject.toml index d2b219503..5764363a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -207,7 +207,7 @@ lint.pydocstyle.convention = "pep257" lint.preview = true [tool.codespell] -skip = '.git,*.lock,tests,docs/cli-reference,CHANGELOG.md,docs/changelog.md' +skip = '.git,*.lock,tests,docs/cli-reference,CHANGELOG.md,docs/changelog.md,docs/llms.txt,docs/llms-full.txt' [tool.pytest.ini_options] filterwarnings = [ diff --git a/scripts/build_llms_txt.py b/scripts/build_llms_txt.py new file mode 100644 index 000000000..99f66a71b --- /dev/null +++ b/scripts/build_llms_txt.py @@ -0,0 +1,390 @@ +"""llms.txt generator for datamodel-code-generator documentation. + +Generates llms.txt and llms-full.txt from zensical.toml nav structure. +See https://llmstxt.org/ for the llms.txt specification. + +Usage: + python scripts/build_llms_txt.py + python scripts/build_llms_txt.py --check # CI: check if files are up to date +""" + +from __future__ import annotations + +import argparse +import re +import sys +from dataclasses import dataclass, field +from fnmatch import fnmatch +from pathlib import Path +from typing import Any + +try: + import tomllib +except ImportError: + import tomli as tomllib + +ROOT_DIR = Path(__file__).parent.parent +DOCS_DIR = ROOT_DIR / "docs" +ZENSICAL_TOML = ROOT_DIR / "zensical.toml" + +OPTIONAL_PATTERNS = [ + "faq.md", + "development-contributing.md", + "cli-reference/manual/*.md", +] + +MAX_DESCRIPTION_LINES = 2 +MAX_DESCRIPTION_LENGTH = 150 +TRUNCATED_DESCRIPTION_LENGTH = 147 + +EMOJI_PATTERN = re.compile( + r"[" + r"\U0001F300-\U0001F9FF" + r"\U0001FA00-\U0001FA6F" + r"\U0001FA70-\U0001FAFF" + r"\U00002702-\U000027B0" + r"\U0001F680-\U0001F6FF" + r"\U0001F1E0-\U0001F1FF" + r"\U00002600-\U000026FF" + r"\U00002300-\U000023FF" + r"\U0000FE00-\U0000FE0F" + r"\U0000200D" + r"]+", + flags=re.UNICODE, +) + + +@dataclass +class PageInfo: + """Information about a documentation page.""" + + title: str + path: str + url: str + description: str + content: str + depth: int = 0 + is_section: bool = False + + +@dataclass +class NavSection: + """A navigation section with optional children.""" + + title: str + path: str | None = None + children: list[NavSection] = field(default_factory=list) + depth: int = 0 + + +def parse_zensical_toml(path: Path) -> dict[str, Any]: + """Parse zensical.toml and extract project configuration.""" + if not path.exists(): + print(f"Error: {path} not found", file=sys.stderr) + sys.exit(1) + + try: + with path.open("rb") as f: + config = tomllib.load(f) + except tomllib.TOMLDecodeError as e: + print(f"Error parsing {path}: {e}", file=sys.stderr) + sys.exit(1) + + project = config.get("project", {}) + return { + "site_name": project.get("site_name", ""), + "site_description": project.get("site_description", ""), + "site_url": project.get("site_url", "").rstrip("/"), + "nav": project.get("nav", []), + } + + +def flatten_nav(nav: list[dict[str, Any]], depth: int = 0) -> list[NavSection]: + """Recursively flatten navigation structure.""" + sections: list[NavSection] = [] + + for item in nav: + for title, value in item.items(): + if isinstance(value, str): + sections.append(NavSection(title=title, path=value, depth=depth)) + elif isinstance(value, list): + section = NavSection(title=title, depth=depth) + section.children = flatten_nav(value, depth + 1) + sections.append(section) + + return sections + + +def remove_emoji(text: str) -> str: + """Remove emoji characters from text.""" + return EMOJI_PATTERN.sub("", text).strip() + + +def extract_page_info(md_path: Path, url: str, depth: int = 0) -> PageInfo | None: + """Extract title and description from a Markdown file.""" + if not md_path.exists(): + print(f"Warning: {md_path} not found, skipping", file=sys.stderr) + return None + + try: + content = md_path.read_text(encoding="utf-8") + except OSError as e: + print(f"Warning: Cannot read {md_path}: {e}", file=sys.stderr) + return None + + lines = content.split("\n") + title = md_path.stem.replace("-", " ").replace("_", " ").title() + description = "" + + in_code_block = False + found_h1 = False + description_lines: list[str] = [] + + for line in lines: + stripped = line.strip() + + if stripped.startswith("```"): + in_code_block = not in_code_block + continue + + if in_code_block: + continue + + if stripped.startswith("# ") and not found_h1: + title = remove_emoji(stripped[2:].strip()) + found_h1 = True + continue + + if found_h1: + if stripped.startswith("## "): + break + + if stripped.startswith("!!!"): + continue + if stripped.startswith("[!["): + continue + if stripped.startswith("!["): + continue + if stripped.startswith("<"): + continue + if stripped.startswith("---"): + continue + if not stripped: + if description_lines: + break + continue + + description_lines.append(stripped) + if len(description_lines) >= MAX_DESCRIPTION_LINES: + break + + if description_lines: + description = " ".join(description_lines) + description = remove_emoji(description) + if len(description) > MAX_DESCRIPTION_LENGTH: + description = description[:TRUNCATED_DESCRIPTION_LENGTH] + "..." + + return PageInfo( + title=title, + path=str(md_path.relative_to(DOCS_DIR)), + url=url, + description=description, + content=content, + depth=depth, + ) + + +def is_optional_page(path: str) -> bool: + """Check if a page should be in the Optional section.""" + return any(fnmatch(path, pattern) for pattern in OPTIONAL_PATTERNS) + + +def collect_pages(sections: list[NavSection], site_url: str, depth: int = 0) -> list[PageInfo]: + """Collect all pages from navigation sections.""" + pages: list[PageInfo] = [] + + for section in sections: + if section.path: + md_path = DOCS_DIR / section.path + path_without_ext = section.path.rsplit(".", 1)[0] + if path_without_ext == "index": + url = f"{site_url}/" + elif path_without_ext.endswith("/index"): + url = f"{site_url}/{path_without_ext[:-6]}/" + else: + url = f"{site_url}/{path_without_ext}/" + + page = extract_page_info(md_path, url, depth) + if page: + pages.append(page) + + if section.children: + pages.extend(collect_pages(section.children, site_url, depth + 1)) + + return pages + + +def _format_page_link(page: PageInfo) -> str: + """Format a page as a markdown link with optional description.""" + desc = f": {page.description}" if page.description else "" + return f"- [{page.title}]({page.url}){desc}" + + +def _render_optional_sections(sections: list[NavSection], page_map: dict[str, PageInfo]) -> list[str]: + """Render optional sections as a flat list of links.""" + lines: list[str] = [] + for section in sections: + if section.path: + page = page_map.get(section.path) + if page: + lines.append(_format_page_link(page)) + elif section.children: + for child in section.children: + if child.path: + page = page_map.get(child.path) + if page: + lines.append(_format_page_link(page)) + return lines + + +def generate_llms_txt(config: dict[str, Any], sections: list[NavSection], pages: list[PageInfo]) -> str: + """Generate llms.txt content.""" + lines: list[str] = [] + + lines.extend((f"# {config['site_name']}", "", f"> {config['site_description']}", "")) + + page_map = {p.path: p for p in pages} + + main_sections: list[NavSection] = [] + optional_sections: list[NavSection] = [] + + for section in sections: + if section.path and is_optional_page(section.path): + optional_sections.append(section) + elif section.children: + has_optional = all(child.path and is_optional_page(child.path) for child in section.children) + if has_optional: + optional_sections.append(section) + else: + main_sections.append(section) + else: + main_sections.append(section) + + def render_section(section: NavSection) -> list[str]: + result: list[str] = [] + + if section.path: + page = page_map.get(section.path) + if page: + result.append(_format_page_link(page)) + elif section.children: + if section.depth == 0: + result.extend((f"## {section.title}", "")) + else: + result.extend((f"### {section.title}", "")) + + for child in section.children: + result.extend(render_section(child)) + + result.append("") + + return result + + for section in main_sections: + section_lines = render_section(section) + lines.extend(section_lines) + + if optional_sections: + lines.extend(("## Optional", "")) + lines.extend(_render_optional_sections(optional_sections, page_map)) + lines.append("") + + while lines and not lines[-1]: + lines.pop() + lines.append("") + + return "\n".join(lines) + + +def generate_llms_full_txt(pages: list[PageInfo]) -> str: + """Generate llms-full.txt with all documentation content.""" + parts: list[str] = [] + + for page in pages: + parts.extend((f"# {page.title}", "", f"Source: {page.url}", "")) + + content = page.content.strip() + if content.startswith("# "): + first_newline = content.find("\n") + if first_newline != -1: + content = content[first_newline + 1 :].strip() + + parts.extend((content, "", "---", "")) + + return "\n".join(parts) + + +def main() -> int: + """Run the llms.txt generator.""" + parser = argparse.ArgumentParser(description="Generate llms.txt files from documentation") + parser.add_argument( + "--check", + action="store_true", + help="Check if files are up to date without modifying", + ) + parser.add_argument( + "--output-dir", + type=Path, + default=DOCS_DIR, + help="Output directory (default: docs/)", + ) + args = parser.parse_args() + + config = parse_zensical_toml(ZENSICAL_TOML) + sections = flatten_nav(config["nav"]) + pages = collect_pages(sections, config["site_url"]) + + llms_txt = generate_llms_txt(config, sections, pages) + llms_full_txt = generate_llms_full_txt(pages) + + llms_txt_path = args.output_dir / "llms.txt" + llms_full_txt_path = args.output_dir / "llms-full.txt" + + if args.check: + errors = [] + + if not llms_txt_path.exists(): + errors.append(f"{llms_txt_path} does not exist") + elif llms_txt_path.read_text(encoding="utf-8") != llms_txt: + errors.append(f"{llms_txt_path} is out of date") + + if not llms_full_txt_path.exists(): + errors.append(f"{llms_full_txt_path} does not exist") + elif llms_full_txt_path.read_text(encoding="utf-8") != llms_full_txt: + errors.append(f"{llms_full_txt_path} is out of date") + + if errors: + for error in errors: + print(f"Error: {error}", file=sys.stderr) + print( + "\nRun 'python scripts/build_llms_txt.py' to regenerate.", + file=sys.stderr, + ) + return 1 + + print("llms.txt files are up to date") + return 0 + + args.output_dir.mkdir(parents=True, exist_ok=True) + + llms_txt_path.write_text(llms_txt, encoding="utf-8") + print(f"Generated {llms_txt_path}") + + llms_full_txt_path.write_text(llms_full_txt, encoding="utf-8") + print(f"Generated {llms_full_txt_path}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tox.ini b/tox.ini index 24286739e..037c2cc23 100644 --- a/tox.ini +++ b/tox.ini @@ -112,6 +112,13 @@ commands = check-wheel-contents --no-config {env_tmp_dir} dependency_groups = pkg-meta +[testenv:llms-txt] +description = Generate llms.txt files (use --check to validate only) +commands = + python scripts/build_llms_txt.py {posargs} +dependency_groups = +no_default_groups = true + [testenv:config-types] description = Generate TypedDict files from config models (use --check to validate only) commands = From 7d9f3c933fafdf21ff9ae5eedc4821284eff8d64 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 3 Jan 2026 06:34:09 +0000 Subject: [PATCH 2/5] Fix codespell skip for llms.txt files --- .github/workflows/codespell.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codespell.yaml b/.github/workflows/codespell.yaml index 19a2370d6..e65eb1c9c 100644 --- a/.github/workflows/codespell.yaml +++ b/.github/workflows/codespell.yaml @@ -27,4 +27,4 @@ jobs: uses: codespell-project/actions-codespell@v2 with: exclude_file: CODE_OF_CONDUCT.md - skip: ./docs/cli-reference + skip: ./docs/cli-reference,./docs/llms.txt,./docs/llms-full.txt From 84afdcd309b0cce55271d028a56ecf4cd928331e Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 3 Jan 2026 07:24:41 +0000 Subject: [PATCH 3/5] Refactor build_llms_txt.py: DRY, TypedDict, walrus operator --- scripts/build_llms_txt.py | 373 ++++++++++++-------------------------- 1 file changed, 115 insertions(+), 258 deletions(-) diff --git a/scripts/build_llms_txt.py b/scripts/build_llms_txt.py index 99f66a71b..5cbd3ad3e 100644 --- a/scripts/build_llms_txt.py +++ b/scripts/build_llms_txt.py @@ -16,7 +16,7 @@ from dataclasses import dataclass, field from fnmatch import fnmatch from pathlib import Path -from typing import Any +from typing import Any, TypedDict try: import tomllib @@ -26,34 +26,25 @@ ROOT_DIR = Path(__file__).parent.parent DOCS_DIR = ROOT_DIR / "docs" ZENSICAL_TOML = ROOT_DIR / "zensical.toml" - -OPTIONAL_PATTERNS = [ - "faq.md", - "development-contributing.md", - "cli-reference/manual/*.md", -] - -MAX_DESCRIPTION_LINES = 2 -MAX_DESCRIPTION_LENGTH = 150 -TRUNCATED_DESCRIPTION_LENGTH = 147 - -EMOJI_PATTERN = re.compile( - r"[" - r"\U0001F300-\U0001F9FF" - r"\U0001FA00-\U0001FA6F" - r"\U0001FA70-\U0001FAFF" - r"\U00002702-\U000027B0" - r"\U0001F680-\U0001F6FF" - r"\U0001F1E0-\U0001F1FF" - r"\U00002600-\U000026FF" - r"\U00002300-\U000023FF" - r"\U0000FE00-\U0000FE0F" - r"\U0000200D" - r"]+", - flags=re.UNICODE, +OPTIONAL_PATTERNS = ("faq.md", "development-contributing.md", "cli-reference/manual/*.md") +SKIP_PREFIXES = ("```", "!!!", "[![", "![", "<", "---") +MAX_DESC_LINES, MAX_DESC_LEN = 2, 150 +EMOJI_RE = re.compile( + r"[\U0001F300-\U0001F9FF\U0001FA00-\U0001FAFF\U00002702-\U000027B0" + r"\U0001F680-\U0001F6FF\U0001F1E0-\U0001F1FF\U00002600-\U000026FF" + r"\U00002300-\U000023FF\U0000FE00-\U0000FE0F\U0000200D]+", ) +class SiteConfig(TypedDict): + """Configuration extracted from zensical.toml.""" + + site_name: str + site_description: str + site_url: str + nav: list[dict[str, Any]] + + @dataclass class PageInfo: """Information about a documentation page.""" @@ -64,7 +55,6 @@ class PageInfo: description: str content: str depth: int = 0 - is_section: bool = False @dataclass @@ -77,312 +67,179 @@ class NavSection: depth: int = 0 -def parse_zensical_toml(path: Path) -> dict[str, Any]: +def parse_zensical_toml(path: Path) -> SiteConfig: """Parse zensical.toml and extract project configuration.""" if not path.exists(): - print(f"Error: {path} not found", file=sys.stderr) - sys.exit(1) - + sys.exit(f"Error: {path} not found") try: with path.open("rb") as f: - config = tomllib.load(f) + project = tomllib.load(f).get("project", {}) except tomllib.TOMLDecodeError as e: - print(f"Error parsing {path}: {e}", file=sys.stderr) - sys.exit(1) - - project = config.get("project", {}) - return { - "site_name": project.get("site_name", ""), - "site_description": project.get("site_description", ""), - "site_url": project.get("site_url", "").rstrip("/"), - "nav": project.get("nav", []), - } + sys.exit(f"Error parsing {path}: {e}") + return SiteConfig( + site_name=project.get("site_name", ""), + site_description=project.get("site_description", ""), + site_url=project.get("site_url", "").rstrip("/"), + nav=project.get("nav", []), + ) def flatten_nav(nav: list[dict[str, Any]], depth: int = 0) -> list[NavSection]: """Recursively flatten navigation structure.""" sections: list[NavSection] = [] - for item in nav: for title, value in item.items(): if isinstance(value, str): sections.append(NavSection(title=title, path=value, depth=depth)) elif isinstance(value, list): - section = NavSection(title=title, depth=depth) - section.children = flatten_nav(value, depth + 1) - sections.append(section) - + sections.append(NavSection(title=title, children=flatten_nav(value, depth + 1), depth=depth)) return sections -def remove_emoji(text: str) -> str: - """Remove emoji characters from text.""" - return EMOJI_PATTERN.sub("", text).strip() - - def extract_page_info(md_path: Path, url: str, depth: int = 0) -> PageInfo | None: """Extract title and description from a Markdown file.""" if not md_path.exists(): - print(f"Warning: {md_path} not found, skipping", file=sys.stderr) - return None - + return print(f"Warning: {md_path} not found, skipping", file=sys.stderr) try: content = md_path.read_text(encoding="utf-8") except OSError as e: - print(f"Warning: Cannot read {md_path}: {e}", file=sys.stderr) - return None - - lines = content.split("\n") - title = md_path.stem.replace("-", " ").replace("_", " ").title() - description = "" - - in_code_block = False - found_h1 = False - description_lines: list[str] = [] - - for line in lines: - stripped = line.strip() - - if stripped.startswith("```"): - in_code_block = not in_code_block - continue - - if in_code_block: - continue - - if stripped.startswith("# ") and not found_h1: - title = remove_emoji(stripped[2:].strip()) - found_h1 = True - continue - - if found_h1: - if stripped.startswith("## "): + return print(f"Warning: Cannot read {md_path}: {e}", file=sys.stderr) + + title, desc_lines, in_code, found_h1 = md_path.stem.replace("-", " ").replace("_", " ").title(), [], False, False + for line in content.split("\n"): + if (s := line.strip()).startswith("```"): + in_code = not in_code + elif in_code: + pass + elif s.startswith("# ") and not found_h1: + title, found_h1 = EMOJI_RE.sub("", s[2:]).strip(), True + elif found_h1: + if s.startswith("## "): break - - if stripped.startswith("!!!"): - continue - if stripped.startswith("[!["): - continue - if stripped.startswith("!["): - continue - if stripped.startswith("<"): - continue - if stripped.startswith("---"): - continue - if not stripped: - if description_lines: + if s.startswith(SKIP_PREFIXES) or (not s and desc_lines): + if not s and desc_lines: break continue + if s: + desc_lines.append(s) + if len(desc_lines) >= MAX_DESC_LINES: + break - description_lines.append(stripped) - if len(description_lines) >= MAX_DESCRIPTION_LINES: - break - - if description_lines: - description = " ".join(description_lines) - description = remove_emoji(description) - if len(description) > MAX_DESCRIPTION_LENGTH: - description = description[:TRUNCATED_DESCRIPTION_LENGTH] + "..." - + desc = EMOJI_RE.sub("", " ".join(desc_lines)).strip() if desc_lines else "" + if len(desc) > MAX_DESC_LEN: + desc = desc[: MAX_DESC_LEN - 3] + "..." return PageInfo( - title=title, - path=str(md_path.relative_to(DOCS_DIR)), - url=url, - description=description, - content=content, - depth=depth, + title=title, path=str(md_path.relative_to(DOCS_DIR)), url=url, description=desc, content=content, depth=depth ) -def is_optional_page(path: str) -> bool: - """Check if a page should be in the Optional section.""" - return any(fnmatch(path, pattern) for pattern in OPTIONAL_PATTERNS) - - def collect_pages(sections: list[NavSection], site_url: str, depth: int = 0) -> list[PageInfo]: """Collect all pages from navigation sections.""" pages: list[PageInfo] = [] - for section in sections: - if section.path: - md_path = DOCS_DIR / section.path - path_without_ext = section.path.rsplit(".", 1)[0] - if path_without_ext == "index": - url = f"{site_url}/" - elif path_without_ext.endswith("/index"): - url = f"{site_url}/{path_without_ext[:-6]}/" - else: - url = f"{site_url}/{path_without_ext}/" - - page = extract_page_info(md_path, url, depth) - if page: + if p := section.path: + base = p.rsplit(".", 1)[0] + url = f"{site_url}/" if base == "index" else f"{site_url}/{base.removesuffix('/index')}/" + if page := extract_page_info(DOCS_DIR / p, url, depth): pages.append(page) - if section.children: pages.extend(collect_pages(section.children, site_url, depth + 1)) - return pages -def _format_page_link(page: PageInfo) -> str: - """Format a page as a markdown link with optional description.""" - desc = f": {page.description}" if page.description else "" - return f"- [{page.title}]({page.url}){desc}" - - -def _render_optional_sections(sections: list[NavSection], page_map: dict[str, PageInfo]) -> list[str]: - """Render optional sections as a flat list of links.""" - lines: list[str] = [] - for section in sections: - if section.path: - page = page_map.get(section.path) - if page: - lines.append(_format_page_link(page)) - elif section.children: - for child in section.children: - if child.path: - page = page_map.get(child.path) - if page: - lines.append(_format_page_link(page)) - return lines - - -def generate_llms_txt(config: dict[str, Any], sections: list[NavSection], pages: list[PageInfo]) -> str: +def generate_llms_txt(config: SiteConfig, sections: list[NavSection], pages: list[PageInfo]) -> str: """Generate llms.txt content.""" - lines: list[str] = [] - - lines.extend((f"# {config['site_name']}", "", f"> {config['site_description']}", "")) - page_map = {p.path: p for p in pages} - main_sections: list[NavSection] = [] - optional_sections: list[NavSection] = [] + def fmt(page: PageInfo) -> str: + return f"- [{page.title}]({page.url})" + (f": {page.description}" if page.description else "") - for section in sections: - if section.path and is_optional_page(section.path): - optional_sections.append(section) - elif section.children: - has_optional = all(child.path and is_optional_page(child.path) for child in section.children) - if has_optional: - optional_sections.append(section) - else: - main_sections.append(section) - else: - main_sections.append(section) - - def render_section(section: NavSection) -> list[str]: - result: list[str] = [] + def is_optional(path: str | None) -> bool: + return path is not None and any(fnmatch(path, pat) for pat in OPTIONAL_PATTERNS) + def render(section: NavSection) -> list[str]: if section.path: - page = page_map.get(section.path) - if page: - result.append(_format_page_link(page)) - elif section.children: - if section.depth == 0: - result.extend((f"## {section.title}", "")) - else: - result.extend((f"### {section.title}", "")) - - for child in section.children: - result.extend(render_section(child)) - - result.append("") - - return result - - for section in main_sections: - section_lines = render_section(section) - lines.extend(section_lines) - - if optional_sections: - lines.extend(("## Optional", "")) - lines.extend(_render_optional_sections(optional_sections, page_map)) + return [fmt(p)] if (p := page_map.get(section.path)) else [] + if not section.children: + return [] + hdr = "##" if section.depth == 0 else "###" + lines = [f"{hdr} {section.title}", ""] + for child in section.children: + lines.extend(render(child)) + return [*lines, ""] + + main, optional = [], [] + for s in sections: + is_opt = (s.path and is_optional(s.path)) or (s.children and all(is_optional(c.path) for c in s.children)) + (optional if is_opt else main).append(s) + + lines = [f"# {config['site_name']}", "", f"> {config['site_description']}", ""] + for s in main: + lines.extend(render(s)) + if optional: + lines.extend(["## Optional", ""]) + lines.extend( + fmt(p) + for s in optional + for item in ([s] if s.path else s.children) + if item.path and (p := page_map.get(item.path)) + ) lines.append("") while lines and not lines[-1]: lines.pop() - lines.append("") - - return "\n".join(lines) + return "\n".join([*lines, ""]) def generate_llms_full_txt(pages: list[PageInfo]) -> str: """Generate llms-full.txt with all documentation content.""" parts: list[str] = [] - for page in pages: - parts.extend((f"# {page.title}", "", f"Source: {page.url}", "")) - content = page.content.strip() - if content.startswith("# "): - first_newline = content.find("\n") - if first_newline != -1: - content = content[first_newline + 1 :].strip() + if content.startswith("# ") and (nl := content.find("\n")) != -1: + content = content[nl + 1 :].strip() + parts.extend([f"# {page.title}", "", f"Source: {page.url}", "", content, "", "---", ""]) + return "\n".join(parts) - parts.extend((content, "", "---", "")) - return "\n".join(parts) +def check_files(files: dict[Path, str]) -> int: + """Check if generated files match expected content.""" + errors = [ + f"{path} does not exist" if not path.exists() else f"{path} is out of date" + for path, expected in files.items() + if not path.exists() or path.read_text(encoding="utf-8") != expected + ] + if errors: + for e in errors: + print(f"Error: {e}", file=sys.stderr) + print("\nRun 'python scripts/build_llms_txt.py' to regenerate.", file=sys.stderr) + return 1 + print("llms.txt files are up to date") + return 0 def main() -> int: """Run the llms.txt generator.""" parser = argparse.ArgumentParser(description="Generate llms.txt files from documentation") - parser.add_argument( - "--check", - action="store_true", - help="Check if files are up to date without modifying", - ) - parser.add_argument( - "--output-dir", - type=Path, - default=DOCS_DIR, - help="Output directory (default: docs/)", - ) + parser.add_argument("--check", action="store_true", help="Check if files are up to date without modifying") + parser.add_argument("--output-dir", type=Path, default=DOCS_DIR, help="Output directory (default: docs/)") args = parser.parse_args() config = parse_zensical_toml(ZENSICAL_TOML) sections = flatten_nav(config["nav"]) pages = collect_pages(sections, config["site_url"]) - - llms_txt = generate_llms_txt(config, sections, pages) - llms_full_txt = generate_llms_full_txt(pages) - - llms_txt_path = args.output_dir / "llms.txt" - llms_full_txt_path = args.output_dir / "llms-full.txt" + files = { + args.output_dir / "llms.txt": generate_llms_txt(config, sections, pages), + args.output_dir / "llms-full.txt": generate_llms_full_txt(pages), + } if args.check: - errors = [] - - if not llms_txt_path.exists(): - errors.append(f"{llms_txt_path} does not exist") - elif llms_txt_path.read_text(encoding="utf-8") != llms_txt: - errors.append(f"{llms_txt_path} is out of date") - - if not llms_full_txt_path.exists(): - errors.append(f"{llms_full_txt_path} does not exist") - elif llms_full_txt_path.read_text(encoding="utf-8") != llms_full_txt: - errors.append(f"{llms_full_txt_path} is out of date") - - if errors: - for error in errors: - print(f"Error: {error}", file=sys.stderr) - print( - "\nRun 'python scripts/build_llms_txt.py' to regenerate.", - file=sys.stderr, - ) - return 1 - - print("llms.txt files are up to date") - return 0 + return check_files(files) args.output_dir.mkdir(parents=True, exist_ok=True) - - llms_txt_path.write_text(llms_txt, encoding="utf-8") - print(f"Generated {llms_txt_path}") - - llms_full_txt_path.write_text(llms_full_txt, encoding="utf-8") - print(f"Generated {llms_full_txt_path}") - + for path, content in files.items(): + path.write_text(content, encoding="utf-8") + print(f"Generated {path}") return 0 From e710c8026770787edf6b71e613f04b4c43aab374 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 3 Jan 2026 08:47:26 +0000 Subject: [PATCH 4/5] docs: update llms.txt files Generated by GitHub Actions --- docs/llms-full.txt | 73 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/docs/llms-full.txt b/docs/llms-full.txt index b76df6144..a22bbf7ae 100644 --- a/docs/llms-full.txt +++ b/docs/llms-full.txt @@ -65,6 +65,14 @@ Source: https://datamodel-code-generator.koxudaxi.dev/ --- +!!! warning "Omitting --output-model-type is deprecated" + Starting from version 0.53.0, omitting `--output-model-type` is deprecated. + The implicit default `pydantic.BaseModel` (Pydantic v1) will be removed in a future version. + + We recommend using `--output-model-type pydantic_v2.BaseModel` for new projects. + +--- + ## ๐Ÿƒ Quick Start ### 1๏ธโƒฃ Create a schema file @@ -24041,7 +24049,11 @@ Generate Pydantic models from JSON Schema definitions. See [Supported Data Types ## ๐Ÿš€ Quick Start ```bash -datamodel-codegen --input person.json --input-file-type jsonschema --output model.py +datamodel-codegen \ + --input person.json \ + --input-file-type jsonschema \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py ``` ## ๐Ÿ“ Example @@ -24174,7 +24186,11 @@ Generate Pydantic models directly from JSON data. Under the hood, the generator ## ๐Ÿš€ Quick Start ```bash -datamodel-codegen --input pets.json --input-file-type json --output model.py +datamodel-codegen \ + --input pets.json \ + --input-file-type json \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py ``` ## ๐Ÿ“ Example @@ -24244,9 +24260,17 @@ Generate Pydantic models from GraphQL schema definitions. ## ๐Ÿš€ Quick Start ```bash -datamodel-codegen --input schema.graphql --input-file-type graphql --output model.py +datamodel-codegen \ + --input schema.graphql \ + --input-file-type graphql \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py ``` +!!! tip "Why `--output-model-type`?" + Starting from version 0.53.0, explicitly specifying `--output-model-type` is recommended. + See [Omitting --output-model-type is deprecated](index.md#omitting---output-model-type-is-deprecated) for details. + !!! note "๐Ÿ“ฆ Installation" GraphQL support requires the `graphql` extra: ```bash @@ -24387,7 +24411,12 @@ print(books) ## ๐ŸŽจ Custom Scalar Types ```bash -datamodel-codegen --input schema.graphql --input-file-type graphql --output model.py --extra-template-data data.json +datamodel-codegen \ + --input schema.graphql \ + --input-file-type graphql \ + --output-model-type pydantic_v2.BaseModel \ + --extra-template-data data.json \ + --output model.py ``` **schema.graphql** @@ -24454,7 +24483,12 @@ as GraphQL servers typically don't expect this field in input data. Use the `--graphql-no-typename` option to exclude this field: ```bash -datamodel-codegen --input schema.graphql --input-file-type graphql --output model.py --graphql-no-typename +datamodel-codegen \ + --input schema.graphql \ + --input-file-type graphql \ + --output-model-type pydantic_v2.BaseModel \ + --graphql-no-typename \ + --output model.py ``` **Before (default):** @@ -26773,7 +26807,11 @@ The `--aliases` option allows you to rename fields in the generated models. This ## ๐Ÿš€ Basic Usage ```bash -datamodel-codegen --input schema.json --output model.py --aliases aliases.json +datamodel-codegen \ + --input schema.json \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py \ + --aliases aliases.json ``` ## ๐Ÿ“‹ Alias File Format @@ -27792,7 +27830,10 @@ Generated code is automatically formatted using code formatters. By default, `bl **Library users**: Explicitly pass `formatters=[Formatter.BLACK, Formatter.ISORT]` to suppress this warning. ```bash -datamodel-codegen --input schema.yaml --output model.py +datamodel-codegen \ + --input schema.yaml \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py ``` This runs the following formatters in order: @@ -27821,10 +27862,18 @@ This runs the following formatters in order: ```bash # Use ruff for both linting and formatting -datamodel-codegen --formatters ruff-check ruff-format --input schema.yaml --output model.py +datamodel-codegen \ + --formatters ruff-check ruff-format \ + --input schema.yaml \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py # Use ruff-format as a black replacement -datamodel-codegen --formatters isort ruff-format --input schema.yaml --output model.py +datamodel-codegen \ + --formatters isort ruff-format \ + --input schema.yaml \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py ``` ### ๐Ÿšซ Disable formatting @@ -27868,7 +27917,11 @@ quote-style = "single" By default, string quote style is determined by your formatter configuration. To force double quotes regardless of configuration: ```bash -datamodel-codegen --use-double-quotes --input schema.yaml --output model.py +datamodel-codegen \ + --use-double-quotes \ + --input schema.yaml \ + --output-model-type pydantic_v2.BaseModel \ + --output model.py ``` This overrides `skip_string_normalization` in black config. From d9c1e5764e3f8a05e3a8d06909c6c4c17daa39d0 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Sat, 3 Jan 2026 08:56:18 +0000 Subject: [PATCH 5/5] Add Python 3.11+ requirement note to llms-txt env --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 037c2cc23..4d2c787b5 100644 --- a/tox.ini +++ b/tox.ini @@ -113,7 +113,7 @@ commands = dependency_groups = pkg-meta [testenv:llms-txt] -description = Generate llms.txt files (use --check to validate only) +description = Generate llms.txt files (use --check to validate only, requires Python 3.11+) commands = python scripts/build_llms_txt.py {posargs} dependency_groups =