How to define mutually exclusive query parameters in Swagger (OpenAPI)?
What about changing your API design ? Currently you have one method, 3 parameters. If I understand well, user must always provide exactly one parameter, and two remaining ones must be unset.
For me, API would be more usable with three endpoints -like
/user/byName?name=
/user/bySite?name=
/user/bySurvey?name=
Mutually exclusive parameters are possible (sort of) in OpenAPI 3.x:
- Define the mutually exclusive parameters as object properties, and use
oneOf
ormaxProperties
to limit the object to just 1 property. - Use the parameter serialization method
style: form
andexplode: true
, so that the object is serialized as?propName=value
.
An example using the minProperties
and maxProperties
constraints:
openapi: 3.0.0
...
paths:
/foo:
get:
parameters:
- in: query
name: filter
required: true
style: form
explode: true
schema:
type: object
properties:
username:
type: string
site:
type: string
survey:
type: string
minProperties: 1
maxProperties: 1
additionalProperties: false
Using oneOf
:
parameters:
- in: query
name: filter
required: true
style: form
explode: true
schema:
type: object
oneOf:
- properties:
username:
type: string
required: [username]
additionalProperties: false
- properties:
site:
type: string
required: [site]
additionalProperties: false
- properties:
survey:
type: string
required: [survey]
additionalProperties: false
Another version using oneOf
:
parameters:
- in: query
name: filter
required: true
style: form
explode: true
schema:
type: object
properties:
username:
type: string
site:
type: string
survey:
type: string
additionalProperties: false
oneOf:
- required: [username]
- required: [site]
- required: [survey]
Note that Swagger UI and Swagger Editor do not support the examples above yet (as of March 2018). This issue seems to cover the parameter rendering part.
There's also an open proposal in the OpenAPI Specification repository to support interdependencies between query parameters so maybe future versions of the Specification will have a better way to define such scenarios.
Unfortunately this isn't possible currently. "required" is just a boolean and there's no way to represent interdependencies between parameters.
Best you can do is make clear the requirements in the parameter descriptions and also put in a custom 400 Bad Request description along the same lines.
There's a bit of discussion at https://github.com/OAI/OpenAPI-Specification/issues/256 about possible ways of implementing this in the next version of the OpenAPI Specification.