Skip to content

🐍 Using datamodel-code-generator as a 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.

📦 Installation

The base package is sufficient when all inputs and references are local. To load an HTTP(S) input or resolve a remote $ref, install the stable HTTP extra:

pip install 'datamodel-code-generator[http]'

The http extra uses HTTPX and is supported and not deprecated. The experimental HTTPX2 backend is available separately:

pip install 'datamodel-code-generator[httpx2]'

The experimental extra is not included in datamodel-code-generator[all]. The default HTTPBackend.AUTO policy selects stable HTTPX when its client module is installed, including when both extras are installed, and selects HTTPX2 only when that module is absent. Require HTTPX2 with --http-backend httpx2, http_backend = "httpx2" under [tool.datamodel-codegen], or the public API:

from urllib.parse import urlparse

from datamodel_code_generator import HTTPBackend, generate

result = generate(
    urlparse("https://example.com/schema.json"),
    http_backend=HTTPBackend.HTTPX2,
)

See HTTP backend selection for the complete automatic and explicit selection rules.

📝 Getting Generated Code as String

When the output parameter is omitted (or set to None), generate() returns the generated code directly as a string:

Note

GenerateConfig requires a Pydantic v2 environment.

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)

📝 Reading Input From a File

Pass a Path to input_ for file input. Plain strings are treated as schema text; if a string points to an existing file and parsing fails, generate() warns and recommends using Path.

from pathlib import Path

from datamodel_code_generator import InputFileType, generate

result = generate(
    input_=Path("example.json"),
    input_file_type=InputFileType.JsonSchema,
)
print(result)

📝 Multiple Module Output

When the schema generates multiple modules, generate() returns a GeneratedModules dictionary mapping module path tuples to generated code:

from datamodel_code_generator import InputFileType, generate, GenerateConfig, GeneratedModules

# Your OpenAPI specification (string schema text, 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:

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:

# 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().

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)

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
AvroParser AvroParserConfig
GraphQLParser GraphQLParserConfig

All config classes inherit from ParserConfig and include additional parser-specific options.

✨ Output:

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