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 }