跳到内容

使用 $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 Reference 表示法,而以 # 开头的部分使用 JSON Pointer 表示法。此表示法允许你指定目标文件或你要引用的文件的特定部分。在前面的示例中,#/components/schemas/User 表示解析从当前文档的根开始,然后依次查找 componentsschemasUser 的值。

$ref 语法

根据 RFC3986$ref 字符串值(JSON Reference)应包含一个 URI,该 URI 标识你要引用的 JSON 值的位置。如果字符串值不符合 URI 语法规则,则会在解析期间导致错误。JSON Reference 对象中除了 $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 规范 明确声明该值可能是引用的位置。例如,不能在 info 部分和 paths 下直接使用 $ref

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 模式完全相同。

没有找到你要找的内容?向社区提问
发现错误?告诉我们