🌐
GitHub
github.com › koxudaxi › datamodel-code-generator
GitHub - koxudaxi/datamodel-code-generator: Python data model generator (Pydantic, dataclasses, TypedDict, msgspec) from OpenAPI, JSON Schema, GraphQL, and raw data (JSON/YAML/CSV). · GitHub
🎯 Generates Pydantic v2, Pydantic v2 dataclass, 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 ... datamodel-codegen --input schema.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --output model.py
Starred by 3.8K users
Forked by 429 users
Languages   Python
🌐
Pydantic
docs.pydantic.dev › latest › integrations › datamodel_code_generator
datamodel-code-generator - Pydantic Validation
# generated by datamodel-codegen: # filename: person.json # timestamp: 2020-05-19T15:07:31+00:00 from __future__ import annotations from typing import Any from pydantic import BaseModel, Field, conint class Pet(BaseModel): name: str | None = None age: int | None = None class Person(BaseModel): first_name: str = Field(description="The person's first name.") last_name: str = Field(description="The person's last name.") age: conint(ge=0) | None = Field(None, description='Age in years.') pets: list[Pet] | None = None comment: Any | None = None
🌐
PyPI
pypi.org › project › datamodel-code-generator › 0.33.0
datamodel-code-generator · PyPI
This code generator creates pydantic v1 and v2 model, dataclasses.dataclass, typing.TypedDict and msgspec.Struct from an openapi file and others. See documentation for more details. To install datamodel-code-generator: $ pip install datamodel-code-generator ·
      » pip install datamodel-code-generator
    
Published   Aug 14, 2025
Version   0.33.0
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator › releases
Releases · koxudaxi/datamodel-code-generator
Default output model switched from Pydantic v1 to v2 - Running datamodel-codegen without specifying --output-model-type now generates Pydantic v2 models (pydantic_v2.BaseModel) instead of Pydantic v1 models (pydantic.BaseModel). Users who depend on the previous default behavior must now explicitly specify --output-model-type pydantic.BaseModel to continue generating Pydantic v1 compatible code.
Author   koxudaxi
🌐
Koxudaxi
datamodel-code-generator.koxudaxi.dev
datamodel-code-generator - datamodel-code-generator
pip install 'datamodel-code-generator[http]' datamodel-codegen --url https://example.com/api/openapi.yaml --output model.py ... [tool.datamodel-codegen] input = "schema.yaml" output = "src/models.py" output-model-type = "pydantic_v2.BaseModel"
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator › issues › 803
Support for Pydantic v2 · Issue #803 · koxudaxi/datamodel-code-generator
July 10, 2022 - koxudaxi / datamodel-code-generator Public · There was an error while loading. Please reload this page. Notifications · You must be signed in to change notification settings · Fork 426 · Star 3.8k · New issueCopy link · New issueCopy link · Closed · Closed · Support for Pydantic v2#803 ·
Author   ofek
🌐
Ubuntu
manpages.ubuntu.com › manpages › resolute › man1 › datamodel-codegen.1.html
Ubuntu Manpage: datamodel-codegen - pydantic code generator from OpenAPI and more
(example: "ref=branch") --input INPUT Input file/directory (default: stdin) --input-file-type {auto,openapi,jsonschema,json,yaml,dict,csv,graphql} Input file type (default: auto) --output OUTPUT Output file (default: stdout) --output-model-type {pydantic.BaseModel,pydantic_v2.BaseModel,dataclasses.dataclass,typing.TypedDict,msgspec.Struct} Output model type (default: pydantic.BaseModel) --url URL Input file URL.
🌐
Docker Hub
hub.docker.com › r › koxudaxi › datamodel-code-generator
koxudaxi/datamodel-code-generator - Docker Image
This code generator creates pydantic v1 and v2⁠ model, dataclasses.dataclass⁠, typing.TypedDict⁠ and msgspec.Struct⁠ from an openapi file and others. See documentation⁠ for more details. To install datamodel-code-generator: $ pip install datamodel-code-generator Copy ·
Find elsewhere
🌐
PyPI
pypi.org › project › improved-datamodel-codegen
improved-datamodel-codegen · PyPI
# generated by datamodel-codegen: # filename: api.yaml # timestamp: 2020-06-02T05:28:24+00:00 from __future__ import annotations from typing import List, Optional from pydantic import AnyUrl, BaseModel, Field class Pet(BaseModel): id: int name: str tag: Optional[str] = None class Pets(BaseModel): __root__: List[Pet] class Error(BaseModel): code: int message: str class Api(BaseModel): apiKey: Optional[str] = Field( None, description='To be used as a dataset parameter value' ) apiVersionNumber: Optional[str] = Field( None, description='To be used as a version parameter value' ) apiUrl: Optional[AnyUrl] = Field( None, description="The URL describing the dataset's fields" ) apiDocumentationUrl: Optional[AnyUrl] = Field( None, description='A URL to the API console for each API' ) class Apis(BaseModel): __root__: List[Api] This code generator creates FastAPI app from an openapi file.
      » pip install improved-datamodel-codegen
    
Published   Mar 07, 2023
Version   1.2.1
🌐
Koxudaxi
koxudaxi.github.io › datamodel-code-generator › what_is_the_difference_between_v1_and_v2
Output Model Types - datamodel-code-generator
datamodel-codegen --input schema.json --output-model-type pydantic.BaseModel --output model.py · 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] ... See Pydantic v2 Migration Guide for details.
🌐
Pydantic
docs.pydantic.dev › 1.10 › datamodel_code_generator
Code Generation - Pydantic
# generated by datamodel-codegen: # filename: person.json # timestamp: 2020-05-19T15:07:31+00:00 from __future__ import annotations from typing import Any, List, Optional from pydantic import BaseModel, Field, conint class Pet(BaseModel): name: Optional[str] = None age: Optional[int] = None class Person(BaseModel): first_name: str = Field(..., description="The person's first name.") last_name: str = Field(..., description="The person's last name.") age: Optional[conint(ge=0)] = Field(None, description='Age in years.') pets: Optional[List[Pet]] = None comment: Optional[Any] = None
🌐
GitHub
github.com › tomercagan › datamodel-code-generator
GitHub - tomercagan/datamodel-code-generator: Pydantic model generator for easy conversion of JSON, OpenAPI, JSON Schema, and YAML data sources.
This code generator creates pydantic model from an openapi file and others. See documentation for more details. ... If you want to resolve $ref for remote files then you should specify http extra option.
Author   tomercagan
🌐
Debian Manpages
manpages.debian.org › unstable › datamodel-codegen › datamodel-codegen.1.en.html
datamodel-codegen(1) — datamodel-codegen — Debian unstable — Debian Manpages
3 weeks ago - Use type alias format for RootModel (e.g., Foo = RootModel[Bar]) instead of class inheritance (Pydantic v2 only) ... Use specialized Enum class (StrEnum, IntEnum). Requires --target-python-version 3.11+ --use-standard-collections, --no-use-standard-collections · Use standard collections for type hinting (list, dict). Default: enabled ... Generate tuple types for arrays with items array syntax when minItems equals maxItems equals items length
Top answer
1 of 1
1

I haven't found a way to make the Globals class use the extended definition of the table

You can change the type of a field in a subclass if you declare the field again using the desired type.

Also, simply adding new fields to the subclass does not seem to work

It looks like you are setting instance attributes in the __init__() method, but fields are declared as class attributes.

This example shows a way to add a calculated field records_by_id to ExtendedTable and use ExtendedTable in ExtendedGlobals:

# File: extensions.py
import json
from typing import Any, Dict, List, Optional

from pydantic import Field, validator

from datamodel import Globals, Record, Table


class ExtendedTable(Table):
    # New fields are declared as class attributes not as instance attributes inside the __init__()
    # Calculated fields usually have a default value or default factory so that you don't have to provide a value
    # I prefer a default_factory for mutable values
    records_by_id: Dict[int, Record] = Field(default_factory=dict)

    # A validator can populate a calculated field
    # Use always=True to run the validator even if a value is not supplied and the default value is used
    @validator("records_by_id", always=True)
    def _calculate_records_by_id(
        cls, value: Dict[int, Record], values: Dict[str, Any]
    ) -> Dict[int, Record]:
        records: Optional[List[Record]] = values.get("records")
        if records is None:
            # The records field was not valid
            # Return value or raise a ValueError instead if you want
            return value
        return {record.id: record for record in records}


class ExtendedGlobals(Globals):
    # You can change the type of a field in a subclass if you declare the field again
    table: ExtendedTable


if __name__ == "__main__":
    records = """
    {
        "table": {
            "records": [{"id": 0, "name": "A"}, {"id": 1, "name": "B"}]
        }
    }
    """

    content = json.loads(records)
    extended_globals = ExtendedGlobals.parse_obj(content)
    print(repr(extended_globals))

Output:

ExtendedGlobals(table=ExtendedTable(records=[Record(id=0, name='A'), Record(id=1, name='B')], records_by_id={0: Record(id=0, name='A'), 1: Record(id=1, name='B')}))
🌐
GitHub
github.com › pydantic › pydantic › blob › main › docs › integrations › datamodel_code_generator.md
pydantic/docs/integrations/datamodel_code_generator.md at main · pydantic/pydantic
November 20, 2024 - # generated by datamodel-codegen: # filename: person.json # timestamp: 2020-05-19T15:07:31+00:00 from __future__ import annotations from typing import Any from pydantic import BaseModel, Field, conint class Pet(BaseModel): name: str | None = None age: int | None = None class Person(BaseModel): first_name: str = Field(description="The person's first name.") last_name: str = Field(description="The person's last name.") age: conint(ge=0) | None = Field(None, description='Age in years.') pets: list[Pet] | None = None comment: Any | None = None
Author   pydantic
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator › blob › main › CHANGELOG.md
datamodel-code-generator/CHANGELOG.md at main · koxudaxi/datamodel-code-generator
Default output model switched from Pydantic v1 to v2 - Running datamodel-codegen without specifying --output-model-type now generates Pydantic v2 models (pydantic_v2.BaseModel) instead of Pydantic v1 models (pydantic.BaseModel). Users who depend on the previous default behavior must now explicitly specify --output-model-type pydantic.BaseModel to continue generating Pydantic v1 compatible code.
Author   koxudaxi
Top answer
1 of 1
2

From the datamodel-code-generator "official documentation" mentioned on the page you reference, datamodel-code-generator can be used as a module to get the dictionary to python-code-string (see https://koxudaxi.github.io/datamodel-code-generator/using_as_module/).

Here is there relevant example code (to avoid problems with their pages changing)

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

Then, assuming that there isn't a way to send in a schema that would cause their parser to generate malicious code, you just need to run

exec(result)

EDIT: Here is a worked out example using the example code. I get an error with your schema, which I have not tried to debug.

>>> 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"]
...                         }
...     }
... }"""
>>> 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)
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

>>> exec(result)
>>> m = Model(**{'number': 1, 'street_name': 'Main', 'street_type': 'Street'})
>>> print(m)
number=1.0 street_name='Main' street_type=<StreetType.Street: 'Street'>
>>>