@@ -192,7 +192,12 @@ class JSONReference(_enum.Enum):
192192
193193
194194class Discriminator (BaseModel ):
195- """Represent OpenAPI discriminator object."""
195+ """Represent OpenAPI discriminator object.
196+
197+ This is an OpenAPI-specific concept for supporting polymorphism.
198+ It identifies which schema applies based on a property value.
199+ Kept in jsonschema.py to avoid circular imports with openapi.py.
200+ """
196201
197202 propertyName : str # noqa: N815
198203 mapping : Optional [dict [str , str ]] = None # noqa: UP045
@@ -517,7 +522,7 @@ def _get_type(
517522 data_formats : dict [str , dict [str , Types ]] | None = None ,
518523) -> Types :
519524 """Get the appropriate Types enum for a given JSON Schema type and format."""
520- if data_formats is None :
525+ if data_formats is None : # pragma: no cover
521526 data_formats = json_schema_data_formats
522527 if type_ not in data_formats :
523528 return Types .any
@@ -768,8 +773,16 @@ def _get_type_with_mappings(self, type_: str, format_: str | None = None) -> Typ
768773
769774 @cached_property
770775 def schema_paths (self ) -> list [tuple [str , list [str ]]]:
771- """Get schema paths for definitions and defs."""
772- return [(s , s .lstrip ("#/" ).split ("/" )) for s in self .SCHEMA_PATHS ]
776+ """Get schema paths for definitions and defs.
777+
778+ Prioritizes the version-appropriate key based on detected schema version,
779+ but checks both for lenient compatibility with mixed-version schemas.
780+ - Draft 4-7: definitions (standard), then $defs (fallback)
781+ - Draft 2019-09+: $defs (standard), then definitions (fallback)
782+ """
783+ primary_key = self .schema_features .definitions_key
784+ ordered_paths = ["#/$defs" , "#/definitions" ] if primary_key == "$defs" else ["#/definitions" , "#/$defs" ]
785+ return [(s , s .lstrip ("#/" ).split ("/" )) for s in ordered_paths ]
773786
774787 @cached_property
775788 def schema_features (self ) -> JsonSchemaFeatures :
@@ -3589,9 +3602,15 @@ def parse_id(self, obj: JsonSchemaObject, path: list[str]) -> None:
35893602
35903603 @contextmanager
35913604 def root_id_context (self , root_raw : dict [str , Any ]) -> Generator [None , None , None ]:
3592- """Context manager to temporarily set the root $id during parsing."""
3605+ """Context manager to temporarily set the root $id during parsing.
3606+
3607+ Uses schema_features.id_field to support both "id" (Draft 4) and "$id" (Draft 6+).
3608+ Falls back to checking both fields for lenient compatibility.
3609+ """
35933610 previous_root_id = self .root_id
3594- self .root_id = root_raw .get ("$id" ) or None
3611+ # Try version-specific field first, then fallback to alternative for compatibility
3612+ id_field = self .schema_features .id_field
3613+ self .root_id = root_raw .get (id_field ) or root_raw .get ("$id" ) or root_raw .get ("id" ) or None
35953614 yield
35963615 self .root_id = previous_root_id
35973616
0 commit comments