From 71249e7f83798ddcf6d3d598b55f00abcb817eca Mon Sep 17 00:00:00 2001 From: p1c2u Date: Sat, 7 Mar 2026 21:52:25 +0000 Subject: [PATCH] OAS 3.1/3.2 discriminator is annotation-only --- openapi_schema_validator/validators.py | 4 +- tests/integration/test_validators.py | 73 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/openapi_schema_validator/validators.py b/openapi_schema_validator/validators.py index e6be03b..2dad167 100644 --- a/openapi_schema_validator/validators.py +++ b/openapi_schema_validator/validators.py @@ -115,12 +115,10 @@ def _build_oas31_validator() -> Any: Draft202012Validator, { # adjusted to OAS - "allOf": oas_keywords.allOf, - "oneOf": oas_keywords.oneOf, - "anyOf": oas_keywords.anyOf, "pattern": oas_keywords.pattern, "description": oas_keywords.not_implemented, # fixed OAS fields + # discriminator is annotation-only in OAS 3.1+ "discriminator": oas_keywords.not_implemented, "xml": oas_keywords.not_implemented, "externalDocs": oas_keywords.not_implemented, diff --git a/tests/integration/test_validators.py b/tests/integration/test_validators.py index b59f31e..60a9c7f 100644 --- a/tests/integration/test_validators.py +++ b/tests/integration/test_validators.py @@ -1107,6 +1107,79 @@ def test_array_prefixitems_invalid(self, validator_class, value): ] assert any(error in str(excinfo.value) for error in errors) + def test_discriminator_is_annotation_only(self, validator_class): + schema = { + "components": { + "schemas": { + "A": { + "type": "object", + "properties": {"kind": {"type": "string"}}, + "required": ["kind"], + }, + "B": { + "type": "object", + "properties": { + "kind": {"type": "string"}, + "other": {"type": "string"}, + }, + "required": ["kind"], + }, + } + }, + "oneOf": [ + {"$ref": "#/components/schemas/A"}, + {"$ref": "#/components/schemas/B"}, + ], + "discriminator": {"propertyName": "kind"}, + } + + validator = validator_class(schema) + + # A payload valid for both schemas A and B + instance = {"kind": "B"} + + # oneOf fails because it matches BOTH A and B, discriminator does not restrict it + with pytest.raises(ValidationError): + validator.validate(instance) + + @pytest.mark.parametrize( + "mapping_ref", + [ + "#/components/schemas/Missing", + "#missing-anchor", + "#bad/frag", + ], + ) + def test_discriminator_unresolvable_reference_ignored( + self, validator_class, mapping_ref + ): + schema = { + "oneOf": [{"$ref": "#/components/schemas/MountainHiking"}], + "discriminator": { + "propertyName": "discipline", + "mapping": {"mountain_hiking": mapping_ref}, + }, + "components": { + "schemas": { + "MountainHiking": { + "type": "object", + "properties": { + "discipline": {"type": "string"}, + "length": {"type": "integer"}, + }, + "required": ["discipline", "length"], + }, + }, + }, + } + + validator = validator_class(schema) + + # It should not raise any referencing errors because discriminator mapping is annotation-only + validator.validate( + {"discipline": "mountain_hiking", "length": 10}, + ) + class TestOAS32ValidatorValidate(TestOAS31ValidatorValidate): """OAS 3.2 uses the OAS 3.2 published dialect resources."""