Skip to content

Create type aliases for nested elements with titles when use-title-as-name is enabled#2891

Merged
koxudaxi merged 2 commits intomainfrom
fix/use-title-as-name-nested-titles
Jan 2, 2026
Merged

Create type aliases for nested elements with titles when use-title-as-name is enabled#2891
koxudaxi merged 2 commits intomainfrom
fix/use-title-as-name-nested-titles

Conversation

@koxudaxi
Copy link
Copy Markdown
Owner

@koxudaxi koxudaxi commented Jan 2, 2026

Fixes: #2887

Summary by CodeRabbit

  • Bug Fixes

    • Prevented title-derived names from leaking into merged schema baselines.
    • Fixed path resolution for nested dictionaries derived from additionalProperties.
  • New Features

    • Broader creation of inline type aliases (including primitive inline types and pattern/property-names cases).
    • Generated additional TypedDict and Pydantic model aliases for pattern/propNames structures.
  • Tests

    • Added tests covering nested-title handling for both TypedDict and Pydantic outputs.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Refines JSON Schema parsing: excludes "title" from base-object merges, broadens title-driven inline type aliasing (including primitives and pattern/propertyName cases), and fixes path resolution for nested additionalProperties parsing.

Changes

Cohort / File(s) Summary
Parser Logic
src/datamodel_code_generator/parser/jsonschema.py
Exclude "title" when building base objects in parse_combined_schema; expand _should_create_type_alias_for_title() to allow primitive inline types, patternProperties, and propertyNames to produce aliases; adjust parse_item() and parse_root_type() to use get_special_path("additionalProperties", ...) for nested dicts.
TypedDict expected output
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py
Add multiple type aliases and Foo TypedDict fields (patternObj, propNamesObj, etc.) to reflect title-based aliasing for nested elements.
Pydantic expected output
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py
Add RootModel classes and extend Foo with optional fields (patternObj, propNamesObj) using Field(..., title=...) to preserve titles.
Tests
tests/main/jsonschema/test_main_jsonschema.py
Add two tests: test_jsonschema_use_title_as_name_nested_titles() and test_jsonschema_use_title_as_name_nested_titles_pydantic() exercising title-as-name behavior for nested schemas.

Sequence Diagram(s)

(omitted — changes are internal parser logic without multi-component runtime interactions requiring a sequence diagram)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • #2889 — Similar edits to src/datamodel_code_generator/parser/jsonschema.py to create named aliases for titled inline types and adjust additionalProperties path handling.

Suggested labels

breaking-change-analyzed

Poem

🐰 A title hid deep in nested trees,
I hopped right in and gave it a name,
Primitives and patterns now dance with ease,
Paths fixed, aliases calling—hop! the same. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main change: creating type aliases for nested elements with titles when use-title-as-name is enabled, which directly addresses the reported issue.
Linked Issues check ✅ Passed The PR implements the requirements from issue #2887 by extending _should_create_type_alias_for_title to handle nested titled elements (arrays, objects, oneOf, anyOf, patternProperties, propertyNames) and improving path resolution for nested types.
Out of Scope Changes check ✅ Passed All changes directly support creating type aliases for nested titled elements: modifications to parse_combined_schema, _should_create_type_alias_for_title, parse_item/parse_root_type path handling, and corresponding test additions are all within scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 2, 2026

📚 Docs Preview: https://pr-2891.datamodel-code-generator.pages.dev

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jan 2, 2026

CodSpeed Performance Report

Merging #2891 will not alter performance

Comparing fix/use-title-as-name-nested-titles (ab3438b) with main (1d221da)

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

Summary

✅ 11 untouched
⏩ 98 skipped1

Footnotes

  1. 98 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/datamodel_code_generator/parser/jsonschema.py (1)

2639-2686: Clean up unused noqa directive.

The # noqa: PLR0911 directive on line 2639 is unused since PLR0911 (too-many-return-statements) is not enabled in the Ruff configuration.

🔎 Suggested fix
-    def _should_create_type_alias_for_title(  # noqa: PLR0911
-        self, item: JsonSchemaObject, name: str
-    ) -> bool:
+    def _should_create_type_alias_for_title(
+        self, item: JsonSchemaObject, name: str
+    ) -> bool:

Expanded type alias logic looks good.

The additions correctly identify primitive types (lines 2676-2686) and enum literals (lines 2670-2675) as candidates for type alias generation when they have titles. This aligns well with the PR objective to create type aliases for nested titled elements.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d221da and d6da8b3.

⛔ Files ignored due to path filters (1)
  • tests/data/jsonschema/use_title_as_name_nested_titles.json is excluded by !tests/data/**/*.json and included by none
📒 Files selected for processing (4)
  • src/datamodel_code_generator/parser/jsonschema.py
  • tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py
  • tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py
  • tests/main/jsonschema/test_main_jsonschema.py
🧰 Additional context used
🧬 Code graph analysis (3)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py (1)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py (1)
  • Foo (42-47)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
  • TypedDict (49-114)
src/datamodel_code_generator/parser/jsonschema.py (2)
src/datamodel_code_generator/util.py (1)
  • model_dump (254-258)
src/datamodel_code_generator/parser/base.py (1)
  • get_special_path (293-295)
🪛 Ruff (0.14.10)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py

9-9: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


12-12: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


15-15: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


18-18: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


21-21: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


24-24: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


27-27: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


30-30: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


33-33: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


36-36: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


39-39: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)

src/datamodel_code_generator/parser/jsonschema.py

2639-2639: Unused noqa directive (non-enabled: PLR0911)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.13 on Windows
  • GitHub Check: 3.11 on macOS
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.10 on macOS
  • GitHub Check: benchmarks
  • GitHub Check: Analyze (python)
🔇 Additional comments (6)
src/datamodel_code_generator/parser/jsonschema.py (3)

1894-1894: LGTM! Excluding "title" enables proper type alias generation for nested elements.

Excluding "title" from the base_object merge prevents the parent schema's title from being propagated to child schemas in combined schemas (anyOf/oneOf). This ensures that each branch can use its own title for type alias generation when use_title_as_name is enabled.


2780-2786: LGTM! Improved path resolution for additionalProperties.

Using get_special_path("additionalProperties", object_path) ensures consistent path marking for internal reference tracking, which improves the correctness of nested type resolution for dict types with additionalProperties.


3002-3004: LGTM! Consistent path handling.

This mirrors the improvement made in parse_item, ensuring that additionalProperties paths are consistently marked using get_special_path across different parsing methods.

tests/main/jsonschema/test_main_jsonschema.py (1)

3107-3154: Nested use_title_as_name tests correctly mirror existing inline-types coverage

Both new tests reuse the same CLI pattern and BLACK_PY313_SKIP gating as the existing use_title_as_name_inline_types tests, but point at the nested-titles schema and goldens. They exercise TypedDict and Pydantic v2 outputs with the right flags (--use-title-as-name, union operator, standard collections, skip-root-model where appropriate), so they should reliably lock in the intended behavior for titled nested items/additionalProperties/oneOf-anyOf branches.

tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py (1)

1-47: TypedDict golden cleanly models nested titled aliases and Foo references

The alias ladder (MyArrayItemMyArray, MyObjectPropMyObject, MyOneOfBranch/MyAnyOfBranch → unions, nested array aliases, etc.) is consistent and keeps Foo’s fields pointing only at named types, which matches the new test’s intent for nested titled elements. Using NotRequired[...] and modern list[...]/dict[...] forms is appropriate for the 3.13-targeted output this golden represents; just ensure your lint configuration either targets ≥3.12 or excludes these expected files if Ruff is run with an older Python target.

tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py (1)

1-65: Pydantic v2 golden correctly promotes nested titled schemas to named RootModels

Each titled nested schema is represented as its own RootModel[...] with a titled root field, and Foo’s optional fields reference those models rather than inlined types, mirroring the TypedDict golden and satisfying the nested use-title-as-name behavior under test. The unions and container shapes align with the issue description and existing pydantic_v2 expectations.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.37%. Comparing base (1d221da) to head (ab3438b).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2891   +/-   ##
=======================================
  Coverage   99.37%   99.37%           
=======================================
  Files          92       92           
  Lines       16152    16165   +13     
  Branches     1906     1909    +3     
=======================================
+ Hits        16051    16064   +13     
  Misses         52       52           
  Partials       49       49           
Flag Coverage Δ
unittests 99.37% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/datamodel_code_generator/parser/jsonschema.py (1)

2639-2690: Expanded aliasing logic is correct, but clean up unused noqa directive.

The expanded _should_create_type_alias_for_title correctly handles:

  • patternProperties and propertyNames cases
  • Primitive types with titles
  • Enum as literal scenarios

However, the # noqa: PLR0911 comment is flagged as unused by Ruff (PLR0911 is not enabled in your configuration).

🔎 Proposed cleanup
-    def _should_create_type_alias_for_title(  # noqa: PLR0911
-        self, item: JsonSchemaObject, name: str
-    ) -> bool:
+    def _should_create_type_alias_for_title(
+        self, item: JsonSchemaObject, name: str
+    ) -> bool:
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6da8b3 and ab3438b.

⛔ Files ignored due to path filters (1)
  • tests/data/jsonschema/use_title_as_name_nested_titles.json is excluded by !tests/data/**/*.json and included by none
📒 Files selected for processing (3)
  • src/datamodel_code_generator/parser/jsonschema.py
  • tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py
  • tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py
🧰 Additional context used
🧬 Code graph analysis (2)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py (2)
tests/data/expected/parser/openapi/openapi_parser_parse_modular/bar.py (1)
  • Field (6-7)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py (1)
  • Foo (54-61)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py (1)
src/datamodel_code_generator/model/typed_dict.py (1)
  • TypedDict (49-114)
🪛 Ruff (0.14.10)
src/datamodel_code_generator/parser/jsonschema.py

2639-2639: Unused noqa directive (non-enabled: PLR0911)

Remove unused noqa directive

(RUF100)

tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py

9-9: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


12-12: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


15-15: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


18-18: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


21-21: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


24-24: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


27-27: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


30-30: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


33-33: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


36-36: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


39-39: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


42-42: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


45-45: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


48-48: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)


51-51: Cannot use type alias statement on Python 3.10 (syntax was added in Python 3.12)

(invalid-syntax)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: py312-isort7 on Ubuntu
  • GitHub Check: 3.10 on macOS
  • GitHub Check: py312-pydantic1 on Ubuntu
  • GitHub Check: 3.12 on Windows
  • GitHub Check: 3.13 on macOS
  • GitHub Check: 3.14 on Ubuntu
  • GitHub Check: 3.12 on macOS
  • GitHub Check: 3.10 on Windows
  • GitHub Check: 3.14 on Windows
  • GitHub Check: 3.11 on Windows
  • GitHub Check: 3.14 on macOS
  • GitHub Check: 3.11 on Ubuntu
  • GitHub Check: 3.13 on Windows
  • GitHub Check: 3.13 on Ubuntu
  • GitHub Check: benchmarks
  • GitHub Check: Analyze (python)
🔇 Additional comments (5)
tests/data/expected/main/jsonschema/use_title_as_name_nested_titles_pydantic.py (1)

1-87: LGTM! Test expectation file structure is correct.

The Pydantic model definitions follow the expected patterns:

  • RootModel usage for type aliases is appropriate
  • Field titles are consistently applied
  • Pattern constraints using constr are correctly specified
  • The Foo model properly references all nested type aliases

This correctly validates the expanded use-title-as-name functionality for patternProperties and propertyNames.

src/datamodel_code_generator/parser/jsonschema.py (3)

1894-1894: Good refinement to exclude title from base object merges.

Excluding "title" when creating the base_object for combined schemas prevents the parent's title from leaking into child schemas during anyOf/oneOf/allOf merging. This ensures titles are only used for their intended purpose in the aliasing logic.


2784-2790: Improved path resolution for nested additionalProperties.

Using get_special_path("additionalProperties", object_path) ensures consistent special path formatting and proper nesting hierarchy for dict types derived from additionalProperties. This aligns with how other special paths like "array" and "enum" are handled throughout the parser.


3006-3010: Consistent path resolution applied to root-level additionalProperties.

This change mirrors the fix at lines 2784-2790, applying the same improved path resolution using get_special_path("additionalProperties", path) for root-level dict types. Maintains consistency across the parser's handling of additionalProperties.

tests/data/expected/main/jsonschema/use_title_as_name_nested_titles.py (1)

1-61: LGTM! Test expectation file correctly uses modern Python syntax.

The type aliases and TypedDict structure correctly validate the expanded use-title-as-name functionality:

  • Modern type statement syntax (PEP 695, Python 3.12+)
  • Proper TypedDict with NotRequired fields
  • Consistent naming from schema titles

The Ruff warnings about Python 3.12 syntax are expected for this generated test expectation file—the generator respects target_python_version configuration, and this output represents the expected result when targeting Python 3.12+.

@koxudaxi koxudaxi merged commit debf5c8 into main Jan 2, 2026
38 checks passed
@koxudaxi koxudaxi deleted the fix/use-title-as-name-nested-titles branch January 2, 2026 08:30
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 2, 2026

Breaking Change Analysis

Result: Breaking changes detected

Reasoning: This PR changes code generation behavior when --use-title-as-name is enabled. Two specific changes affect output: (1) The _should_create_type_alias_for_title method now returns true for additional cases (patternProperties, propertyNames, and primitive types with titles), causing more type aliases to be generated. (2) The parse_combined_schema method now excludes title from the base object during merging, preventing title leakage to child schemas. While these are bug fixes for issue #2887, they change generated output for existing users of --use-title-as-name with schemas containing titles on nested elements.

Content for Release Notes

Code Generation Changes


This analysis was performed by Claude Code Action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 2, 2026

🎉 Released in 0.52.0

This PR is now available in the latest release. See the release notes for details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

use-title-as-name sometimes get ignored

1 participant