跳至內容

使用 $ref

當您記錄 API 時,常見的做法是在多個 API 資源中使用某些功能。在這種情況下,您可以為此類元素建立程式碼片段,以便在需要時多次使用它們。使用 OpenAPI 3.0,您可以參考託管在任何位置的定義。它可以是同一伺服器,也可以是另一個伺服器,例如 GitHub、SwaggerHub 等。若要參考定義,請使用 $ref 關鍵字

1
$ref: "reference to definition"

例如,假設您有下列綱要物件,您想在回應中使用的物件

JSON 範例
1
"components":
2
{
3
"schemas":
4
{
5
"user":
6
{
7
"properties":
8
{ "id": { "type": "integer" }, "name": { "type": "string" } },
9
},
10
},
11
}
YAML 範例
1
components:
2
schemas:
3
User:
4
properties:
5
id:
6
type: integer
7
name:
8
type: string

若要參考該物件,您需要在回應中新增 $ref 和對應的路徑

JSON 範例
1
"responses":
2
{
3
"200":
4
{
5
"description": "The response",
6
"schema": { "$ref": "#/components/schemas/user" },
7
},
8
}
YAML 範例
1
responses:
2
"200":
3
description: The response
4
schema:
5
$ref: "#/components/schemas/User"

$ref 的值使用 JSON 參考 表示法,而以 # 開頭的部分則使用 JSON 指標 表示法。此表示法可讓您指定要參考的目標檔案或檔案的特定部分。在先前的範例中,#/components/schemas/User 表示解析從目前文件的根目錄開始,然後依序尋找 componentsschemasUser 的值。

$ref 語法

根據 RFC3986$ref 字串值 (JSON 參考) 應包含 URI,以識別您正在參考的 JSON 值的位置。如果字串值不符合 URI 語法規則,則會在解析期間導致錯誤。JSON 參考物件中除了 $ref 之外的任何成員都會被忽略。請查看此清單,以了解特定情況下 JSON 參考的範例值

  • 本機參考$ref: '#/definitions/myElement' # 表示移至目前文件的根目錄,然後依序尋找元素 definitionsmyElement
  • 遠端參考$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 下直接使用

1
openapi: 3.0.0
2
3
# Incorrect!
4
info:
5
$ref: info.yaml
6
paths:
7
$ref: paths.yaml

但是,您可以對個別路徑進行 $ref,如下所示

1
paths:
2
/users:
3
$ref: "../resources/users.yaml"
4
/users/{userId}:
5
$ref: "../resources/users-by-id.yaml"

$ref 和同級元素

$ref 的任何同級元素都會被忽略。這是因為 $ref 的運作方式是將其自身及其層級上的所有內容替換為它指向的定義。請考慮以下範例

1
components:
2
schemas:
3
Date:
4
type: string
5
format: date
6
7
DateWithExample:
8
$ref: "#/components/schemas/Date"
9
description: Date schema extended with a `default` value... Or not?
10
default: 2000-01-01

在第二個綱要中,descriptiondefault 屬性會被忽略,因此這個綱要最終與參考的 Date 綱要完全相同。

找不到您要尋找的內容嗎? 向社群提問
發現錯誤? 請告訴我們