diff --git a/src/openapi_parser/builders/schema.py b/src/openapi_parser/builders/schema.py index fcb60ba..c0503b7 100644 --- a/src/openapi_parser/builders/schema.py +++ b/src/openapi_parser/builders/schema.py @@ -111,6 +111,21 @@ def merge_all_of_schemas(original_data: dict[str, Any]) -> dict[str, Any]: return schema_dict +def build_discriminator(value: dict[str, Any]) -> Discriminator: + """Build a Discriminator object from raw data. + + Args: + value: Raw discriminator data + + Returns: + Discriminator object + """ + return Discriminator( + property_name=value["propertyName"], + mapping=value.get("mapping", {}), + ) + + class SchemaFactory: """Factory for creating schema objects from raw dicts.""" @@ -262,19 +277,6 @@ def _one_of(self, data: dict[str, Any]) -> OneOf: def create_inner_schemas(schemas: list[dict[str, Any]]) -> list[Schema]: return [self.create(x) for x in schemas] - def build_discriminator(discriminator_data: dict[str, Any]) -> Discriminator: - discriminator = Discriminator( - property_name=discriminator_data["propertyName"], - ) - - if "mapping" in discriminator_data: - discriminator.mapping = { - key: self.create(schema) - for key, schema in discriminator_data["mapping"].items() - } - - return discriminator - attrs_map = { "schemas": PropertyMeta(name="oneOf", cast=create_inner_schemas), "discriminator": PropertyMeta( @@ -289,7 +291,13 @@ def _any_of(self, data: dict[str, Any]) -> AnyOf: def create_inner_schemas(schemas: list[dict[str, Any]]) -> list[Schema]: return [self.create(x) for x in schemas] - attrs_map = {"schemas": PropertyMeta(name="anyOf", cast=create_inner_schemas)} + attrs_map = { + "schemas": PropertyMeta(name="anyOf", cast=create_inner_schemas), + "discriminator": PropertyMeta( + name="discriminator", + cast=build_discriminator, + ), + } if "type" in data: return AnyOf(**extract_attrs(data, attrs_map)) diff --git a/src/openapi_parser/specification.py b/src/openapi_parser/specification.py index 892a6cb..8f185d8 100644 --- a/src/openapi_parser/specification.py +++ b/src/openapi_parser/specification.py @@ -161,7 +161,7 @@ class Discriminator: """Polymorphism discriminator.""" property_name: str - mapping: dict[str, Any] | None = field(default_factory=dict) + mapping: dict[str, str] | None = field(default_factory=dict) @dataclass @@ -177,6 +177,7 @@ class AnyOf(Schema): """AnyOf composition schema.""" schemas: list[Schema] = field(default_factory=list) + discriminator: Discriminator | None = None @dataclass diff --git a/tests/builders/schema/test_anyof.py b/tests/builders/schema/test_anyof.py index bf47c04..f654727 100644 --- a/tests/builders/schema/test_anyof.py +++ b/tests/builders/schema/test_anyof.py @@ -8,6 +8,7 @@ AnyOf, Array, Boolean, + Discriminator, Integer, Number, Object, @@ -142,6 +143,32 @@ ], ), ), + ( + { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ], + "discriminator": { + "propertyName": "objectType", + "mapping": { + "str": "SomeTarget", + "int": "OtherTarget", + }, + }, + }, + AnyOf( + type=DataType.ANY_OF, + schemas=[ + String(type=DataType.STRING), + Integer(type=DataType.INTEGER), + ], + discriminator=Discriminator( + property_name="objectType", + mapping={"str": "SomeTarget", "int": "OtherTarget"}, + ), + ), + ), ) diff --git a/tests/builders/schema/test_oneof.py b/tests/builders/schema/test_oneof.py index e5721bb..8306dfc 100644 --- a/tests/builders/schema/test_oneof.py +++ b/tests/builders/schema/test_oneof.py @@ -102,17 +102,8 @@ "discriminator": { "propertyName": "objectType", "mapping": { - "objectType1": { - "type": "string", - "maxLength": 1, - "minLength": 0, - "pattern": "[0-9]", - "format": "uuid", - }, - "objectType2": { - "type": "integer", - "format": "int32", - }, + "objectType1": "objectType1", + "objectType2": "objectType2", }, }, }, @@ -134,17 +125,8 @@ discriminator=Discriminator( property_name="objectType", mapping={ - "objectType1": String( - type=DataType.STRING, - max_length=1, - min_length=0, - pattern="[0-9]", - format=StringFormat.UUID, - ), - "objectType2": Integer( - type=DataType.INTEGER, - format=IntegerFormat.INT32, - ), + "objectType1": "objectType1", + "objectType2": "objectType2", }, ), ), diff --git a/tests/data/swagger.yml b/tests/data/swagger.yml index 8e711c0..2d1e7fb 100644 --- a/tests/data/swagger.yml +++ b/tests/data/swagger.yml @@ -304,3 +304,13 @@ components: format: uri example: 'https://github.com/manchenkoff/openapi3-parser' description: 'User Avatar URL' + + Payload: + oneOf: + - type: string + - type: integer + discriminator: + propertyName: payloadType + mapping: + str: 'SomeTarget' + int: 'OtherTarget' diff --git a/tests/openapi_fixture.py b/tests/openapi_fixture.py index ae0b03e..206df11 100644 --- a/tests/openapi_fixture.py +++ b/tests/openapi_fixture.py @@ -15,12 +15,14 @@ Array, Contact, Content, + Discriminator, Encoding, Info, Integer, License, Link, Object, + OneOf, Operation, Parameter, Path, @@ -301,6 +303,17 @@ def create_specification() -> Specification: ), ], ), + "Payload": OneOf( + type=DataType.ONE_OF, + schemas=[ + String(type=DataType.STRING), + Integer(type=DataType.INTEGER), + ], + discriminator=Discriminator( + property_name="payloadType", + mapping={"str": "SomeTarget", "int": "OtherTarget"}, + ), + ), } security: list[dict[str, Any]] = [{"Basic": []}]