使用 $ref
當您記錄 API 時,常見的做法是在多個 API 資源中使用某些功能。在這種情況下,您可以為此類元素建立程式碼片段,以便在需要時多次使用它們。使用 OpenAPI 3.0,您可以參考託管在任何位置的定義。它可以是同一伺服器,也可以是另一個伺服器,例如 GitHub、SwaggerHub 等。若要參考定義,請使用 $ref
關鍵字
1$ref: "reference to definition"
例如,假設您有下列綱要物件,您想在回應中使用的物件
1"components":2 {3 "schemas":4 {5 "user":6 {7 "properties":8 { "id": { "type": "integer" }, "name": { "type": "string" } },9 },10 },11 }
1components:2 schemas:3 User:4 properties:5 id:6 type: integer7 name:8 type: string
若要參考該物件,您需要在回應中新增 $ref
和對應的路徑
1"responses":2 {3 "200":4 {5 "description": "The response",6 "schema": { "$ref": "#/components/schemas/user" },7 },8 }
1responses:2 "200":3 description: The response4 schema:5 $ref: "#/components/schemas/User"
$ref
的值使用 JSON 參考 表示法,而以 #
開頭的部分則使用 JSON 指標 表示法。此表示法可讓您指定要參考的目標檔案或檔案的特定部分。在先前的範例中,#/components/schemas/User
表示解析從目前文件的根目錄開始,然後依序尋找 components
、schemas
和 User
的值。
$ref 語法
根據 RFC3986,$ref
字串值 (JSON 參考) 應包含 URI,以識別您正在參考的 JSON 值的位置。如果字串值不符合 URI 語法規則,則會在解析期間導致錯誤。JSON 參考物件中除了 $ref
之外的任何成員都會被忽略。請查看此清單,以了解特定情況下 JSON 參考的範例值
- 本機參考 –
$ref: '#/definitions/myElement'
#
表示移至目前文件的根目錄,然後依序尋找元素definitions
和myElement
。 - 遠端參考 –
$ref: 'document.json'
使用位於相同伺服器且位於相同位置的整個文件。- 位於同一個資料夾中的文件元素 –
$ref: 'document.json#/myElement'
- 位於上層資料夾中的文件元素 –
$ref: '../document.json#/myElement'
- 位於另一個資料夾中的文件元素 –
$ref: '../another-folder/document.json#/myElement'
- 位於同一個資料夾中的文件元素 –
- URL 參考 –
$ref: 'http://path/to/your/resource'
使用位於不同伺服器上的整個文件。- 儲存在不同伺服器上的文件的特定元素 –
$ref: 'http://path/to/your/resource.json#/myElement'
- 位於不同伺服器上的文件,使用相同的通訊協定 (例如 HTTP 或 HTTPS) –
$ref: '//anotherserver.com/files/example.json'
- 儲存在不同伺服器上的文件的特定元素 –
注意:在 YAML 中使用本機參考 (例如 #/components/schemas/User
) 時,請將值括在引號中:'#/components/schemas/User'
。否則它會被視為註解。
跳脫字元
/
和 ~
是 JSON 指標中的特殊字元,當按字面使用時 (例如在路徑名稱中) 需要跳脫。
字元 | 使用以下方式跳脫 |
---|---|
~ | ~0 |
/ | ~1 |
例如,若要參考路徑 /blogs/{blog_id}/new~posts
,您會使用
1$ref: "#/paths/~1blogs~1{blog_id}~1new~0posts"
注意事項
可以使用 $ref 的位置
一個常見的誤解是 $ref
允許在 OpenAPI 規格檔案中的任何位置使用。實際上,$ref
只允許在 OpenAPI 3.0 規格 明確指出該值可以是參考的位置。例如,$ref
無法在 info
區段和 paths
下直接使用
1openapi: 3.0.02
3# Incorrect!4info:5 $ref: info.yaml6paths:7 $ref: paths.yaml
但是,您可以對個別路徑進行 $ref
,如下所示
1paths:2 /users:3 $ref: "../resources/users.yaml"4 /users/{userId}:5 $ref: "../resources/users-by-id.yaml"
$ref 和同級元素
$ref
的任何同級元素都會被忽略。這是因為 $ref
的運作方式是將其自身及其層級上的所有內容替換為它指向的定義。請考慮以下範例
1components:2 schemas:3 Date:4 type: string5 format: date6
7 DateWithExample:8 $ref: "#/components/schemas/Date"9 description: Date schema extended with a `default` value... Or not?10 default: 2000-01-01
在第二個綱要中,description
和 default
屬性會被忽略,因此這個綱要最終與參考的 Date
綱要完全相同。