oneOf, anyOf, allOf, not
OpenAPI 3.0 提供了几个关键词,您可以使用它们来组合 Schema。您可以使用这些关键词创建复杂的 Schema,或根据多个条件验证值。
除了这些,还有一个 not
关键词,您可以使用它来确保值不符合指定的 Schema。
oneOf
使用 oneOf
关键词来确保给定数据符合指定 Schema 中的一个。
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) 中验证请求体。您可以根据对象类型,使用它来验证请求体是否包含有关要更新对象的所有必要信息。请注意,内联或引用的 Schema 必须是Schema 对象,而不是标准的 JSON Schema。现在,进行验证。以下 JSON 对象符合其中一个 Schema,因此请求体是正确的
1{ "bark": true, "breed": "Dingo" }
以下 JSON 对象不符合两个 Schema,因此请求体是不正确的
1{ "bark": true, "hunts": true }
以下 JSON 对象同时符合两个 Schema,因此请求体是不正确的——因为它应该只符合其中一个 Schema,因为我们使用了 oneOf
关键词。
1{ "bark": true, "hunts": true, "breed": "Husky", "age": 3 }
allOf
OpenAPI 允许您使用 allOf
关键词组合和扩展模型定义。allOf
接受一个对象定义数组,这些定义用于独立验证,但共同构成一个单一对象。然而,它并不意味着模型之间存在层次结构。为此,您应该包含 discriminator
。要符合 allOf
,客户端提供的数据必须符合所有给定的子 Schema。在以下示例中,allOf
作为一种工具,将特定情况下使用的 Schema 与通用 Schema 结合起来。为了更清晰,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 操作更新宠物项所需的所有信息。它要求用户指定要更新的项的类型,并根据其选择针对指定的 Schema 进行验证。请注意,内联或引用的 Schema 必须是Schema 对象,而不是标准的 JSON Schema。对于该示例,以下所有请求体都是有效的
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 "pet_type": "Cat",7 "bark": true # The `Cat` schema does not have the `bark` property8}
anyOf
使用 anyOf
关键词来根据给定子 Schema 中的任意数量进行数据验证。也就是说,数据可以同时符合一个或多个子 Schema。
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
请注意,内联或引用的 Schema 必须是Schema 对象,而不是标准的 JSON Schema。在此示例中,以下 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}
以下示例无效,因为它不包含这两个 Schema 所需的任何属性
1{ "nickname": "Mr. Paws", "hunts": false }
anyOf 与 oneOf 之间的区别
oneOf
匹配正好一个子 Schema,而 anyOf
可以匹配一个或多个子 Schema。为了更好地理解这种区别,请使用上面的示例,但将 anyOf
替换为 oneOf
。当使用 oneOf
时,以下请求体是无效的,因为它同时匹配两个 Schema 而不仅仅是一个
1{ "nickname": "Fido", "pet_type": "Dog", "age": 4 }
not
not
关键词并非严格意义上的 Schema 组合,但它与上面提到的所有关键词一样,有助于您修改 Schema 并使其更具体。
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 }