如何在Swagger(OpenAPI)中定义互斥的查询参数?

49

我在Swagger中有一系列参数,就像这样

                    "parameters": [
                    {
                        "name": "username",
                        "description": "Fetch username by username/email",
                        "required": false,
                        "type": "string",
                        "paramType": "query"
                    },
                    {
                        "name": "site",
                        "description": "Fetch username by site",
                        "required": false,
                        "type": "string",
                        "paramType": "query"
                    },
                    {
                        "name": "survey",
                        "description": "Fetch username by survey",
                        "required": false,
                        "type": "string",
                        "paramType": "query"
                    }
                ],

必须填写一个参数,但不重要是哪一个,其他参数可以留空。在Swagger中有没有表示这一点的方法?


很遗憾,看起来这个功能不可用。 - lorless
4个回答

41
相互排斥的参数在OpenAPI 3.x中是可能的(某种程度上):
- 将相互排斥的参数定义为对象属性,并使用oneOfmaxProperties将对象限制为仅1个属性。 - 使用参数序列化方法style: formexplode: true,以便将对象序列化为?propName=value
以下是使用minPropertiesmaxProperties约束的示例:
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

使用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

使用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]

注意,截至2018年3月,Swagger UI和Swagger Editor尚不支持上述示例(此问题似乎涉及参数呈现部分)。
在OpenAPI规范存储库中还有一个开放的提案,支持查询参数之间的相互依赖性,因此未来版本的规范可能会有更好的定义这种情况的方式。

2
我有什么遗漏的吗?因为这对于我在AWS的API网关上似乎没有进行任何验证。 - omega_prime
1
@omega_prime AWS API Gateway不支持oneOf和其他一些OpenAPI功能。 - Helen

18

很不幸,目前这是不可能的。"required"只是一个布尔值,没有办法表示参数之间的相互依存关系。

您可以做的最好的事情是在参数描述中明确说明要求,并在同样的基础上添加自定义的400错误请求描述。

关于在下一个OpenAPI规范版本中实现此功能的可能方式,有一些讨论可参考https://github.com/OAI/OpenAPI-Specification/issues/256


3
OpenAPI 3.0有一种描述互斥参数的方法,参见此答案 - Helen

6

您考虑改变API设计吗?

目前您只有一个方法和三个参数。如果我理解正确,用户必须始终提供一个参数,而其他两个参数必须未设置。

对我来说,如果您有三个端点,API将更易用 - 如下所示:

/user/byName?name=
/user/bySite?name=
/user/bySurvey?name=

11
解决了技术问题,但不是非常符合RESTful原则。 - Craig Bayley

3

我理解得对吗,你的建议是在这种情况下生成API /users?name=name&filterType=[name|site|survey]?我同意这个建议,因为这更符合Restful的规范,我们只有一个单一的资源,这正是应该的(同时还要保持API的简洁和可用性)。 - Bartosz Bilicki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接