oneOf, anyOf, allOf, not
OpenAPI 3.0 提供了几个关键字,您可以使用它们来组合模式。您可以使用这些关键字来创建复杂的模式,或针对多个条件验证值。
此外,还有一个 not
关键字,您可以使用它来确保该值对于指定的模式无效。
oneOf
使用 oneOf
关键字来确保给定数据对于指定的模式之一有效。
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 oneOf:9 - $ref: "#/components/schemas/Cat"10 - $ref: "#/components/schemas/Dog"11 responses:12 "200":13 description: Updated14
15components:16 schemas:17 Dog:18 type: object19 properties:20 bark:21 type: boolean22 breed:23 type: string24 enum: [Dingo, Husky, Retriever, Shepherd]25 Cat:26 type: object27 properties:28 hunts:29 type: boolean30 age:31 type: integer
上面的示例展示了如何在“更新”操作 (PATCH) 中验证请求体。您可以使用它来验证请求体是否包含要更新的对象的必要信息,具体取决于对象类型。请注意,内联或引用的模式必须是模式对象,而不是标准的 JSON 模式。现在,进行验证。以下 JSON 对象对于其中一个模式是有效的,因此请求体是正确的
1{ "bark": true, "breed": "Dingo" }
以下 JSON 对象对于两个模式都无效,因此请求体是不正确的
1{ "bark": true, "hunts": true }
以下 JSON 对象对于两个模式都有效,因此请求体是不正确的 – 它应该只对其中一个模式有效,因为我们正在使用 oneOf
关键字。
1{ "bark": true, "hunts": true, "breed": "Husky", "age": 3 }
allOf
OpenAPI 允许您使用 allOf
关键字组合和扩展模型定义。allOf
接受一个对象定义数组,这些定义用于独立验证,但组合在一起构成单个对象。不过,它并不意味着模型之间存在层次结构。为此,您应该包含 discriminator
。要符合 allOf
,客户端提供的数据必须符合所有给定的子模式。在下面的示例中,allOf
用作将特定情况下使用的模式与通用模式组合的工具。为了更清晰,oneOf
也与 discriminator
一起使用。
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 oneOf:9 - $ref: "#/components/schemas/Cat"10 - $ref: "#/components/schemas/Dog"11 discriminator:12 propertyName: pet_type13 responses:14 "200":15 description: Updated16
17components:18 schemas:19 Pet:20 type: object21 required:22 - pet_type23 properties:24 pet_type:25 type: string26 discriminator:27 propertyName: pet_type28
29 Dog: # "Dog" is a value for the pet_type property (the discriminator value)30 allOf: # Combines the main `Pet` schema with `Dog`-specific properties31 - $ref: "#/components/schemas/Pet"32 - type: object33 # all other properties specific to a `Dog`34 properties:35 bark:36 type: boolean37 breed:38 type: string39 enum: [Dingo, Husky, Retriever, Shepherd]40
41 Cat: # "Cat" is a value for the pet_type property (the discriminator value)42 allOf: # Combines the main `Pet` schema with `Cat`-specific properties43 - $ref: "#/components/schemas/Pet"44 - type: object45 # all other properties specific to a `Cat`46 properties:47 hunts:48 type: boolean49 age:50 type: integer
如您所见,此示例验证了请求体的内容,以确保它包含使用 PUT 操作更新宠物项所需的所有信息。它要求用户指定应更新的项的类型,并根据他们的选择针对指定的模式进行验证。请注意,内联或引用的模式必须是模式对象,而不是标准的 JSON 模式。对于该示例,以下所有请求体都有效
1{2 "pet_type": "Cat",3 "age": 34}5
6{7 "pet_type": "Dog",8 "bark": true9}10
11{12 "pet_type": "Dog",13 "bark": false,14 "breed": "Dingo"15}
以下请求体无效
1{2 "age": 3 # Does not include the pet_type property3}4
5
6
7{8 "pet_type": "Cat",9 "bark": true # The `Cat` schema does not have the `bark` property10}
anyOf
使用 anyOf
关键字来验证数据是否符合给定子模式中的任何数量的模式。也就是说,数据可能同时对一个或多个子模式有效。
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 anyOf:9 - $ref: "#/components/schemas/PetByAge"10 - $ref: "#/components/schemas/PetByType"11 responses:12 "200":13 description: Updated14
15components:16 schemas:17 PetByAge:18 type: object19 properties:20 age:21 type: integer22 nickname:23 type: string24 required:25 - age26
27 PetByType:28 type: object29 properties:30 pet_type:31 type: string32 enum: [Cat, Dog]33 hunts:34 type: boolean35 required:36 - pet_type
请注意,内联或引用的模式必须是模式对象,而不是标准的 JSON 模式。使用此示例,以下 JSON 请求体是有效的
1{2 "age": 13}4
5{6 "pet_type": "Cat",7 "hunts": true8}9
10{11 "nickname": "Fido",12 "pet_type": "Dog",13 "age": 414}
以下示例是无效的,因为它不包含两个模式的任何必需属性
1{ "nickname": "Mr. Paws", "hunts": false }
anyOf 和 oneOf 之间的区别
oneOf
精确匹配一个子模式,而 anyOf
可以匹配一个或多个子模式。为了更好地理解差异,请使用上面的 示例,但将 anyOf
替换为 oneOf
。当使用 oneOf
时,以下请求体是无效的,因为它匹配两个模式而不仅仅是一个
1{ "nickname": "Fido", "pet_type": "Dog", "age": 4 }
not
not
关键字并不完全组合模式,但与上面提到的所有关键字一样,它有助于您修改模式并使其更加具体。
1paths:2 /pets:3 patch:4 requestBody:5 content:6 application/json:7 schema:8 $ref: "#/components/schemas/PetByType"9 responses:10 "200":11 description: Updated12
13components:14 schemas:15 PetByType:16 type: object17 properties:18 pet_type:19 not:20 type: integer21 required:22 - pet_type
在这个例子中,用户应指定 pet_type
的值,该值可以是除整数之外的任何类型(即,它应该是数组、布尔值、数字、对象或字符串)。以下请求体是有效的
1{ "pet_type": "Cat" }
而以下请求体是无效的
1{ "pet_type": 11 }