Breaking Changes
Code Generation Changes
- Generated default field syntax changed - Fields with structured defaults (dicts, lists, model references) now use
Field(default_value, validate_default=True)instead ofdefault_factory=lambda: TypeAdapter(...).validate_python(...)ordefault_factory=lambda: Model.model_validate(...). This produces simpler, more readable code but changes the generated output format. (#3050) - TypeAdapter import removed from generated code - Generated models no longer import
TypeAdapterfrom pydantic sincevalidate_default=Truehandles validation natively. (#3050) - Default value handling for model-referencing fields rewritten - Fields with defaults referencing Pydantic models (BaseModel, RootModel, type aliases) now generate
Field(<raw_value>, validate_default=True)instead ofdefault_factory=lambda: Model.model_validate(...),default_factory=lambda: TypeAdapter(...).validate_python(...), ordefault_factory=lambda: Model(...). Empty collection defaults changed fromdefault_factory=list/default_factory=dicttoField([], validate_default=True)/Field({}, validate_default=True). The generated code is semantically equivalent under Pydantic v2 but textually different, which will break snapshot tests or tooling that matches exact output.pydantic.TypeAdapteris no longer imported in generated code. (#3070) - Default values for model-referencing fields now use
validate_default=Trueinstead ofdefault_factorylambdas - Fields with structured defaults (dicts, lists, or scalars referencing Pydantic models/RootModels) previously generateddefault_factory=lambda: ModelName.model_validate(value)ordefault_factory=lambda: ModelName(value). They now generateField(value, validate_default=True), producing simpler but different output. Empty collection defaults changed fromdefault_factory=list/default_factory=dicttoField([], validate_default=True)/Field({}, validate_default=True). Users who regenerate code will see different output. (#3071)
Before:After:count: CountType | None = Field(default_factory=lambda: CountType(10)) items: dict[str, Item] | None = Field(default_factory=dict, title='Items')
count: CountType | None = Field(10, validate_default=True) items: dict[str, Item] | None = Field({}, title='Items', validate_default=True)
- Default values for fields referencing models now use
validate_default=Trueinstead ofdefault_factory=lambda:- Fields with structured defaults (dicts/lists) that reference Pydantic models previously generateddefault_factory=lambda: Model.model_validate(...)ordefault_factory=lambda: TypeAdapter(Type).validate_python(...)patterns. They now generate the raw default value directly withvalidate_default=True(e.g.,Field({'key': 'val'}, validate_default=True)instead ofField(default_factory=lambda: Model.model_validate({'key': 'val'}))). This changes the generated code output and may affect users who depend on the exact generated code structure, pin generated output in tests, or use custom post-processing. The runtime behavior should be equivalent for Pydantic v2 users. (#3072) TypeAdapterimport removed from generated code - Generated code no longer importspydantic.TypeAdapterfor default value handling. Code that previously usedTypeAdapter(...).validate_python(...)in default factories now uses inline defaults withvalidate_default=True. (#3072)- Integer and boolean discriminator values now supported in generated Literal types - Discriminator fields previously only generated string literal values. They now support
intandbooldiscriminator values (e.g.,Literal[1]instead ofLiteral['1']), which changes generated code for schemas using integer discriminator mappings. (#3072)
API/CLI Changes
ValidatedDefaultandWrappedDefaultclasses removed - These internal classes were exported fromdatamodel_code_generator.model.baseand have been removed. Code importing these types will break:(#3050)# Before (broken) from datamodel_code_generator.model.base import ValidatedDefault, WrappedDefault
SUPPORTS_WRAPPED_DEFAULTandSUPPORTS_VALIDATED_DEFAULTclass variables removed - These flags were removed from theDataModelbase class. Custom model classes that override these variables will see attribute errors. (#3050)- Internal types
ValidatedDefaultandWrappedDefaultremoved - Thedatamodel_code_generator.model._typesmodule was deleted andValidatedDefault/WrappedDefaultare no longer exported fromdatamodel_code_generator.model.base. Code that imports or subclasses these types will break. TheSUPPORTS_WRAPPED_DEFAULTandSUPPORTS_VALIDATED_DEFAULTclass variables were removed fromDataModeland its subclasses; custom model classes referencing these attributes will need updating. (#3070) - Removed
WrappedDefault,ValidatedDefaultclasses andSUPPORTS_WRAPPED_DEFAULT,SUPPORTS_VALIDATED_DEFAULTclass variables - TheWrappedDefaultandValidatedDefaultclasses fromdatamodel_code_generator.model._types(re-exported viadatamodel_code_generator.model.base) have been deleted. TheDataModelclass variablesSUPPORTS_WRAPPED_DEFAULTandSUPPORTS_VALIDATED_DEFAULThave also been removed. Code that imports or references these will break. (#3071) - New
--allow-remote-refs/--no-allow-remote-refsCLI option andallow_remote_refsconfig field - Remote$reffetching over HTTP/HTTPS now emits a deprecation warning by default. Pass--allow-remote-refsto suppress the warning, or--no-allow-remote-refsto block remote fetching entirely. In a future version, remote fetching will be disabled by default. Users relying on remote$refresolution should add--allow-remote-refsto their invocations to avoid the deprecation warning and prepare for the future default change. (#3072) - New
SchemaFetchErrorexception for HTTP fetch failures - Remote schema fetching now raisesSchemaFetchError(instead of propagating rawhttpxexceptions) on HTTP errors, non-2xx status codes, or unexpected HTML responses. Users catching specifichttpxexceptions from remote ref resolution will need to catchSchemaFetchErrorinstead. (#3072)
Error Handling Changes
- Missing local
$refnow raisesErrorinstead ofFileNotFoundError- Previously, when a$refpointed to a non-existent local file, a rawFileNotFoundErrorpropagated to callers. Now it raisesdatamodel_code_generator.Errorwith the message"$ref file not found: <path>". Programmatic users catchingFileNotFoundErrorspecifically will need to catchErrorinstead (#3051) - HTTP fetch failures now raise
SchemaFetchErrorinstead of propagating raw exceptions - HTTP errors (4xx/5xx status codes), unexpected HTML responses, and transport errors (DNS, timeout, connection) that previously resulted in downstream YAML/JSON parse errors or rawhttpxexceptions now raiseSchemaFetchError(a subclass ofError) before parsing is attempted. Users catching specific parse errors orhttpxexceptions for these scenarios will need to update their error handling (#3051) - HTTP fetch errors now raise
SchemaFetchErrorinstead of raw httpx exceptions - Theget_body()function inhttp.pynow catches HTTP errors and raisesSchemaFetchError(a newErrorsubclass) for HTTP status >= 400, network failures, and unexpected HTML responses. Code that caught rawhttpxexceptions from remote schema fetching will need to catchSchemaFetchErrorinstead. (#3071) - Remote
$reffetching now emitsFutureWarningwithout--allow-remote-refs- Fetching remote HTTP/HTTPS$refreferences without explicitly passing--allow-remote-refsnow emits aFutureWarningdeprecation warning. In a future version, remote fetching will be disabled by default. Users relying on implicit remote ref fetching should add--allow-remote-refsto suppress the warning. (#3071) - HTTP fetch errors now raise
SchemaFetchErrorwith validation of response content type - Previously, fetching a remote$refthat returned an HTML error page would silently pass the HTML through as schema content. Now it raisesSchemaFetchErrorif the response hastext/htmlcontent type or a 4xx/5xx status code. This may cause previously-silent failures to become loud errors. (#3072)
Default Behavior Changes
- Implicit remote
$reffetching now emitsFutureWarning- When a$refresolves to an HTTP(S) URL and--allow-remote-refsis not explicitly passed, the tool still fetches the remote reference but emits aFutureWarning. This may cause failures in environments running with-W error(warnings as errors) or strict warning filters. Pass--allow-remote-refsexplicitly to suppress the warning (#3051) - Remote
$reffetching now emits aFutureWarning- When the parser encounters an HTTP/HTTPS$refwithout--allow-remote-refsbeing explicitly set, aFutureWarningis emitted warning that remote fetching will be disabled by default in a future version. Pass--allow-remote-refsto silence the warning, or--no-allow-remote-refsto block remote fetching immediately. (#3070)
Custom Template Update Required
- Type alias templates updated with
fieldsguard - All six type alias templates (TypeAliasAnnotation.jinja2,TypeAliasType.jinja2,TypeStatement.jinja2,UnionTypeAliasAnnotation.jinja2,UnionTypeAliasType.jinja2,UnionTypeStatement.jinja2) now wrap the main body in{% if fields %}...{% else %}blocks that fall back to{{ base_class }}when no fields are present. Users with custom copies of these templates must add the same guard or handle the empty-fields case. (#3070) - Type alias Jinja2 templates now require
fieldsguard andbase_classfallback - The built-in templatesTypeAliasAnnotation.jinja2,TypeAliasType.jinja2,TypeStatement.jinja2, and their Union variants now wrap field access in{%- if fields %}...{%- else %}blocks with abase_classfallback for empty field lists. Users with custom templates derived from the old versions will need to add similar guards. (#3071) - Type alias templates (
TypeAliasAnnotation.jinja2,TypeAliasType.jinja2,TypeStatement.jinja2, and their Union variants) now handle an emptyfieldslist with a fallback tobase_class- If you have custom copies of these templates, they need to be updated to include the new{%- if fields %}...{%- else %}...{%- endif %}branching logic. Without this update, custom templates may error whenfieldsis empty. (#3072)
What's Changed
- Use validate_default=True for structured union defaults by @butvinm in #3050
- Switch download badge from pepy.tech to pypistats.org by @koxudaxi in #3052
- Update projects list with notable AI/LLM ecosystem projects by @koxudaxi in #3053
- Add ryaml as optional YAML backend for faster parsing by @koxudaxi in #3055
- Update release draft model and preserve breaking changes by @koxudaxi in #3057
- Add --allow-remote-refs to disable HTTP fetching of $ref by default by @butvinm in #3051
- Fix type alias template crash with reuse_model on empty fields by @butvinm in #3060
- Fix non-string OpenAPI discriminator literals by @koxudaxi in #3070
- Support JSON files for mapping options by @koxudaxi in #3071
- Refresh project usage list by @koxudaxi in #3072
Full Changelog: 0.55.0...0.56.0