Skip to content

Root Models and Type Aliases

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.

:warning: Notes and limitations

This functionality experimental! Here are a few known issues: - RootModel and type aliases do not fully support field-specific metadata (default, alias, etc). See 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

Pydantic v1 vs v2

The type of type alias generated depends on the Pydantic version:

  • Pydantic v2: Uses TypeAliasType (Python 3.9-3.11) or type statement (Python 3.12+)
  • Pydantic v1: Uses TypeAlias because Pydantic v1 cannot handle TypeAliasType objects

Example

Input JSON Schema

model.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

$ datamodel-codegen --input model.json --input-file-type jsonschema --output model.py

Generated Model

model.py

# 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

$ datamodel-codegen --input model.json --input-file-type jsonschema --use-type-alias --output model.py

Generated Model (Python 3.10+)

model.py

# 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

Generated Model (Python 3.9)

model.py

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

from __future__ import annotations

from typing import Any, Optional, Union

from pydantic import BaseModel
from typing_extensions import TypeAlias

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

$ datamodel-codegen --input model.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --output model.py

Generated Model

model.py

# 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 TypeAliasType (Python 3.9-3.11)

$ datamodel-codegen --input model.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --use-type-alias --output model.py

Generated Model

model.py

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

from __future__ import annotations

from typing import Any, Optional, Union

from pydantic import BaseModel
from typing_extensions import TypeAliasType

Model = TypeAliasType("Model", Any)


UserId = TypeAliasType("UserId", str)


Status = TypeAliasType("Status", Union[str, int])


class User(BaseModel):
    id: Optional[UserId] = None
    status: Optional[Status] = None

Generating type statement (Python 3.12+)

$ 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

model.py

# 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