Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docs/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24345,8 +24345,6 @@ The following features are tracked in the codebase with their implementation sta
| Feature | Introduced | Status | Notes |
|---------|------------|--------|-------|
| `$anchor` | 2019-09 | ❌ Not supported | Use `$ref` with `$id` instead |
| `$recursiveRef` / `$recursiveAnchor` | 2019-09 | ✅ Supported | Statically resolved to self-reference |
| `$dynamicRef` / `$dynamicAnchor` | 2020-12 | ✅ Supported | Statically resolved to self-reference |
| `unevaluatedProperties` | 2019-09 | ❌ Not supported | Use `additionalProperties` instead |
| `unevaluatedItems` | 2019-09 | ❌ Not supported | Use `additionalItems` instead |
| `contentMediaType` | Draft 7 | ❌ Not supported | Content type hints ignored |
Expand Down
2 changes: 0 additions & 2 deletions docs/supported_formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,6 @@ The following features are tracked in the codebase with their implementation sta
| Feature | Introduced | Status | Notes |
|---------|------------|--------|-------|
| `$anchor` | 2019-09 | ❌ Not supported | Use `$ref` with `$id` instead |
| `$recursiveRef` / `$recursiveAnchor` | 2019-09 | ✅ Supported | Statically resolved to self-reference |
| `$dynamicRef` / `$dynamicAnchor` | 2020-12 | ✅ Supported | Statically resolved to self-reference |
| `unevaluatedProperties` | 2019-09 | ❌ Not supported | Use `additionalProperties` instead |
| `unevaluatedItems` | 2019-09 | ❌ Not supported | Use `additionalItems` instead |
| `contentMediaType` | Draft 7 | ❌ Not supported | Content type hints ignored |
Expand Down
14 changes: 3 additions & 11 deletions src/datamodel_code_generator/parser/jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1576,15 +1576,16 @@ def _build_anchor_indexes(self, obj: JsonSchemaObject, path: list[str]) -> None:
root_len = len(root_key)
if root_len < len(path):
suffix_parts = path[root_len:]
# Strip leading '#' from fragment markers (e.g. '#/$defs' -> '$defs')
first = suffix_parts[0]
if first.startswith("#"):
suffix_parts = [first[1:].lstrip("/"), *suffix_parts[1:]]
ref_path = "#/" + "/".join(suffix_parts)
else:
ref_path = "#"
if obj.recursiveAnchor:
self._recursive_anchor_index.setdefault(root_key, []).append(ref_path)
anchors = self._recursive_anchor_index.setdefault(root_key, [])
if ref_path not in anchors:
anchors.append(ref_path)
if obj.dynamicAnchor:
self._dynamic_anchor_index.setdefault(root_key, {}).setdefault(obj.dynamicAnchor, ref_path)

Expand All @@ -1602,7 +1603,6 @@ def _resolve_recursive_ref(self, item: JsonSchemaObject, path: list[str]) -> str
anchors = self._recursive_anchor_index.get(root_key, [])
if not anchors:
return "#"
# Build root-relative path for comparison
root_len = len(root_key)
if root_len < len(path):
suffix_parts = path[root_len:]
Expand All @@ -1612,8 +1612,6 @@ def _resolve_recursive_ref(self, item: JsonSchemaObject, path: list[str]) -> str
current_ref = "#/" + "/".join(suffix_parts)
else:
current_ref = "#" # pragma: no cover
# Find the best matching anchor: path prefix with longest match
# best defaults to "#" (root anchor fallback)
best = "#"
best_len = 0
for anchor_ref in anchors:
Expand Down Expand Up @@ -3022,10 +3020,8 @@ def parse_item( # noqa: PLR0911, PLR0912, PLR0914, PLR0915
item,
root_type_path,
)
# Resolve $recursiveRef to $ref (JSON Schema 2019-09)
if item.recursiveRef and not item.ref:
return self.get_ref_data_type(self._resolve_recursive_ref(item, path) or "#")
# Resolve $dynamicRef to $ref (JSON Schema 2020-12)
if item.dynamicRef and not item.ref:
return self.get_ref_data_type(self._resolve_dynamic_ref(item) or item.dynamicRef)
if item.is_ref_with_nullable_only and item.ref:
Expand Down Expand Up @@ -4151,11 +4147,9 @@ def _parse_file( # noqa: PLR0912, PLR0915
# parse $id before parsing $ref
root_obj = self._validate_schema_object(raw, path_parts or ["#"])
self.parse_id(root_obj, path_parts)
# Build $recursiveAnchor index for root object
if root_obj.recursiveAnchor:
root_key = tuple(path_parts)
self._recursive_anchor_index.setdefault(root_key, []).append("#")
# Build $dynamicAnchor index for root object
if root_obj.dynamicAnchor:
root_key = tuple(path_parts)
self._dynamic_anchor_index.setdefault(root_key, {}).setdefault(root_obj.dynamicAnchor, "#")
Expand All @@ -4173,12 +4167,10 @@ def _parse_file( # noqa: PLR0912, PLR0915
definition_path = [*path_parts, schema_path, key]
obj = self._validate_schema_object(model, definition_path)
self.parse_id(obj, definition_path)
# Build $recursiveAnchor index for definitions
if obj.recursiveAnchor:
root_key = tuple(path_parts)
ref_path = "#/" + schema_path.lstrip("#/") + "/" + key
self._recursive_anchor_index.setdefault(root_key, []).append(ref_path)
# Build $dynamicAnchor index for definitions
if obj.dynamicAnchor:
root_key = tuple(path_parts)
ref_path = "#/" + schema_path.lstrip("#/") + "/" + key
Expand Down
Loading