Better support for OpenAPI OneOf
mbierma opened this issue · 1 comments
mbierma commented
OpenAPI supports the OneOf
keyword to allow the combining of schemas. This could be used to allow an endpoint to validate data against one of the specified schemas -- an example from the link is copied below:
paths:
/pets:
patch:
requestBody:
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
responses:
'200':
description: Updated
components:
schemas:
Dog:
type: object
properties:
bark:
type: boolean
breed:
type: string
enum: [Dingo, Husky, Retriever, Shepherd]
Cat:
type: object
properties:
hunts:
type: boolean
age:
type: integer
It appears that OneOf
support was added in #18, but I haven't been able to get multiple input schemas to work with Marshmallow -- although I could be missing something.
As initially mentioned in #48 (comment), it would be great if something like this were possible
mbierma commented
Closing this for now, but posting a potential workaround by using oneofschema and a custom FieldConverter
:
class FooSchema(marshmallow.Schema):
foo = marshmallow.fields.String(required=True)
class BarSchema(marshmallow.Schema):
bar = marshmallow.fields.Integer(required=True)
class MyUberSchema(OneOfSchema):
type_schemas = {"foo": FooSchema, "bar": BarSchema}
def get_obj_type(self, obj):
if isinstance(obj, Foo):
return "foo"
elif isinstance(obj, Bar):
return "bar"
else:
raise Exception("Unknown object type: {}".format(obj.__class__.__name__))
class TestSchema(marshmallow.Schema):
test = marshmallow.fields.Nested(MyUberSchema())
class OneOfConverter(FieldConverter):
MARSHMALLOW_TYPE = OneOfSchema
def convert(self, obj, context):
subschemas = []
for value in obj.type_schemas.values():
subschemas.append(context.convert(value(), context))
return {sw.one_of: subschemas}
response_converter_registry.register_types([OneOfConverter()])
request_body_converter_registry.register_types([OneOfConverter()])