Self-hosted service
koxudaxi/datamodel-code-generator avatar
koxudaxi/datamodel-code-generator

datamodel-code-generator: Turning Schemas into Pydantic v2 Models Without Hand-Writing a Field

Project brief: Generate Pydantic v2 models, dataclasses, TypedDict, and msgspec.Struct from OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON/YAML/CSV.

4,018 stars460 forksPythonMIT

At a glance

What is it?
A Python CLI that converts OpenAPI, JSON Schema, GraphQL, Avro, Protobuf, and raw JSON/YAML/CSV into Pydantic v2, dataclasses, TypedDict, or msgspec. The core judgement: it saves time on mechanical model writing, but you must verify the generated code against your schema's semantics.
Who is it for?
Adopt datamodel-code-generator if you maintain OpenAPI, JSON Schema, or GraphQL specs and want Pydantic v2, dataclass, TypedDict, or msgspec models generated in seconds. Do not adopt it for one-off scripts where the schema is trivial, or where you need full control over every field annotation.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

Why You Would Generate Models Instead of Writing Them

Hand-writing Python models for a large OpenAPI spec or a JSON Schema with hundreds of properties is slow and error prone. You copy field names, types, defaults, and descriptions, and you risk drifting from the source of truth. datamodel-code-generator exists to close that gap. It reads a schema and emits a Python module with classes that match the schema's structure. The intended audience is teams that already have a schema as the contract, for example an API specification or a data interchange format, and want type-safe Python objects without manual transcription. The README positions it as a tool that produces type-safe, validated code ready for your IDE and type checker. That claim is plausible because the output uses Pydantic's Field and ConfigDict, which give runtime validation and static typing benefits.

The Input and Output Matrix: More Than Just JSON Schema

The generator accepts OpenAPI 3, AsyncAPI, JSON Schema, Apache Avro, XML Schema, Protocol Buffers/gRPC, GraphQL, MCP tool schemas, and raw JSON, YAML, or CSV. On the output side, it can produce Pydantic v2 BaseModel, Pydantic v2 dataclass, plain dataclasses, TypedDict, or msgspec.Struct. That breadth is unusual. Most code generators focus on one input or one output. Here you can take a GraphQL schema and emit TypedDict, or take an Avro file and emit Pydantic v2. The README also mentions a special input mode: --input-model path/to/file.py:ClassName, which retargets an existing Python class to a different output type. That means you can migrate a dataclass to Pydantic v2 without rewriting the class body. The documentation does not show a full example of that mode, so you would need to check the CLI reference for exact syntax, but the feature is real and it addresses a common migration pain.

How Generation Actually Works: From Schema to Annotated Fields

The mechanism is straightforward: you pass a schema file, specify the input file type, choose an output model type, and the tool walks the schema structure. For a JSON Schema object, it maps each property to a Python field. Required properties become required fields, optional ones get defaults or become Optional. The README's example output shows the details. A property with an enum becomes a StrEnum class. A property with a minimum becomes Annotated[int | None, Field(ge=0)]. A property with a default gets that default in the field definition. The generated class includes model_config = ConfigDict(populate_by_name=True). That config is important for OpenAPI compatibility, because it allows population by the original schema field names. The tool also handles $ref, allOf, oneOf, and anyOf, according to the README. How exactly oneOf is represented is not shown in the truncated material, which is a gap you should test yourself. The output is formatted with black and isort by default, though you can switch to a builtin formatter for speed.

Getting It Running: Commands and Installation Paths

The recommended installation for standalone CLI use is uv tool install datamodel-code-generator. Conda users can run conda install -c conda-forge datamodel-code-generator. For projects that should pin the generator version, add it as a development dependency with uv add --dev datamodel-code-generator. The basic command from the README is: datamodel-codegen --input schema.json --input-file-type jsonschema --output-model-type pydantic_v2.BaseModel --preset standard-py312-20260826 --output model.py. The preset name encodes the target Python version; py312 means Python 3.12. There is also a practical-py312-20260826 preset that the README says is more schema-aware: it preserves schema-authored names, reuses models, and embeds generated documentation. That distinction matters. The standard preset is a baseline, while the practical one likely produces more idiomatic output for real-world schemas. For remote $ref resolution, you need the http extra: pip install 'datamodel-code-generator[http]'. GraphQL support requires the graphql extra, and Protobuf support requires the protobuf extra. Docker images run as a non-root appuser, so you must make bind-mounted output directories writable by that user or pass --user "$(id -u):$(id -g)".

The Preset System: A New Way to Lock Down Output Style

The README introduces presets, which are named configurations that bundle a set of options. The quick start uses standard-py312-20260826, and the documentation links to a presets page. Preset names include the target Python version, which suggests the output is tuned to that version's syntax. For example, a Python 3.12 preset likely uses the new type union syntax (int | None) and StrEnum, both of which appear in the example output. The practical preset goes further by preserving schema-authored names and reusing models. That is a meaningful difference. If you have a schema where property names are snake_case and you want to keep them, the standard preset might mangle them, while the practical one respects them. The exact behavior is not in the truncated README, so you would need to consult the presets page. This preset system is a recent addition, judging by the release timeline, and it gives teams a way to standardize generation across a codebase. The trade-off is that preset names include a date stamp, so they will age and you will need to update them as new presets are released.

Where It Falls Short: Formatter Dependencies and Missing Details

The most concrete limitation in the README is the default formatting behavior. By default, the generated Python is formatted with black and isort. That means the generator depends on those external tools being installed. If you run it in a minimal environment without them, generation may fail or slow down. The README suggests adding --formatters builtin for faster generation without external formatter dependencies. That flag is the escape hatch, but it only works for standard generated model modules, not for every possible output. A second limitation is the lack of detail on how complex schema constructs are handled. The README lists $ref, allOf, oneOf, anyOf, enums, and nested types as supported, but it does not show the generated output for a oneOf or anyOf case. Those constructs are where code generators often make opinionated choices, for example wrapping a union in a discriminated union or using a plain Union type. You cannot know which approach this tool takes without running it. A third limitation is the experimental HTTPX2 backend. The README says it is not included in the all extra, and you must explicitly install datamodel-code-generator[httpx2] and pass --http-backend httpx2. That experimental status means you should not rely on it for production pipelines until it stabilizes.

A Real Alternative: Hand-Written Models or Other Generators

The obvious alternative is writing models by hand. That gives you full control over field names, types, and validation logic, but it costs time and invites drift. Another alternative is using a different code generator, such as openapi-generator, which generates client and server code in many languages, not just Python models. The difference in approach is significant: openapi-generator is a full API toolchain, while datamodel-code-generator is focused purely on Python model classes. If you only need Python models, the latter is lighter and more direct. If you need a complete client SDK with API call methods, openapi-generator is the more appropriate tool. There is also the option of using Pydantic's own TypeAdapter to validate data against a schema at runtime, without generating classes at all. That approach avoids the generation step entirely, but it loses the static typing benefits of having real classes. For teams that want static typing, generation is the better fit.

Maintenance and Upgrade Cost: What the Release Cadence Implies

The repository is actively maintained, with the last push on 2026-08-29 and three releases in the same week: 0.76.0, 0.75.1, and 0.75.0. That cadence means you will see frequent updates. The README's mention of presets with date stamps, such as standard-py312-20260826, reinforces that the tool's output style evolves. If you pin the generator version, you freeze the output style, which is good for reproducibility. If you do not pin, new releases may change the generated code format, which could break your tests or your type checking. The MIT license is permissive, so there are no licensing constraints on using or redistributing the generated code. The generated code itself is yours; the generator's license applies to the tool, not the output. The README notes that community packages exist for Debian, Ubuntu, nixpkgs, and openSUSE, but versions vary, so you should prefer the official PyPI or conda-forge distribution for consistency. The documentation site and playground are part of the project, and the playground runs in the browser with Pyodide, which means you can test generation without installing anything. That is a low-cost way to evaluate the tool before committing to it.

Editorial conclusion

Adopt datamodel-code-generator if you maintain OpenAPI, JSON Schema, or GraphQL specs and want Pydantic v2, dataclass, TypedDict, or msgspec models generated in seconds. Do not adopt it for one-off scripts where the schema is trivial, or where you need full control over every field annotation. Before relying on it, verify the generated models against your schema's edge cases: check how $ref, oneOf, and anyOf are resolved, and confirm that enums and defaults match your runtime expectations. Also pin the generator version in your dev dependencies to avoid surprise changes from new releases.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Community notes

Community notes