# 🐍 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](./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:

!!! note
    `GenerateConfig` requires a Pydantic v2 environment.

```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)
```

### 📝 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`.

```python
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:

```python
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:

```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` |
| `AvroParser` | `AvroParserConfig` |
| `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
