Skip to main content

KCL OpenAPI Spec

OpenAPI 允许 API 提供方规范地描述 API 操作和模型,并基于它生成自动化工具和特定语言的客户端。

KCL OpenAPI 文件结构

依据 OpenAPI 3.0 规范,OpenAPI 文件中应至少包含 openapi、components、 info、paths 四种根节点对象,KCL OpenAPI 聚焦于其中模型定义的部分,即 OpenAPI 文件中的 definitions,而描述操作的 Restful API 部分(即 OpenAPI 文件中的 paths)则不属于 KCL OpenAPI 定义的范畴。 ​

注:除以上列出的节点外,OpenAPI 官方规范还支持 servers、security、tags、externalDocs 四种可选的根节点,但都不是 KCL OpenAPI 所关心的,因此用户无需填写这部分内容,即使填写了也不会产生任何影响。 ​

OpenAPI 顶层对象类型含义KCL OpenAPI 工具支持情况
swaggerstringopenapi 版本信息必填项,目前支持 openapi 2.0,即合法取值为 "2.0"
definitionsDefinition Object模型定义必填项
infoInfo Object当前 API 文件的元数据信息,例如标题、描述信息、版本、开源协议等必填项,定义当前 OpenAPI 文件的基本信息,不会输出到 KCL 代码,但可用于 Swagger-UI 工具可视化展示

为方便初学者快速理解,下面给出一个典型的 KCL OpenAPI 文件(截取自 swagger example Petstore)应包含的节点图示。KCL OpenAPI 工具重点关注其中的 definitions 节点,可以看到文件中定义了两个模型(Pet 和 Category),并且 Pet 模型中包含三个属性(name、id、category)

KCL schema

KCL 中使用 schema 结构来定义配置数据的“类型”,关于 KCL schema,可参考文档:传送门 在 definitions 节点下新增 definition 元素,即可定义 KCL schema. 示例: 下例在 KCL 代码中定义了 Pet、Category 两个 schema,同样地,其对应的 OpenAPI 也在 definitions 节点下包含这两个模型的描述。

# KCL schema:
schema Pet:
name: str
id?: int
category?: Category

schema Category:
name?: str

# 对应的 OpenAPI 描述
{
"definitions": {
"Pet": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"id": {
"type": "integer",
"format": "int64"
},
"category": {
"$ref": "#/definitions/Category"
}
},
"required": [
"name"
]
},
"Category": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
},
"swagger": "2.0",
"info": {
"title": "demo",
"version": "v1"
}
}

schema 名称

在 KCL 中,schema 名称紧跟在 schema 关键字后声明,在 OpenAPI 中,模型的名称通过 definition 元素的 key 来定义。

schema 类型

KCL schema 在 OpenAPI 中的类型为 "object". 例如上例中 "Pet" 的 "type" 值应为 "object".

schema 属性

KCL schema 中可以定义若干属性,属性的声明一般包含如下几部分:

  • 属性注解:可选,以 @ 开头,例如 @deprecated 注解表示属性被废弃
  • 属性访问修饰符(final):可选,声明当前属性的值不可被修改
  • 属性名称:必须
  • 属性 optional 修饰符(?):可选,带问号表示当前属性为可选属性,可以不被赋值。反之,不带问号表示必填属性
  • 属性类型:必须,可以是基本数据类型,也可以是 schema 类型, 或者是前述两种类型的并集
  • 属性默认值:非必须

它们与 OpenAPI 规范的对应关系如下:

KCL schema 属性元素OpenAPI 元素
属性注解暂不支持,计划扩展一个 deprecate 字段用于描述 deprecated 注解
属性名称properties 节点下,每个属性的 key 即为属性名称
属性 optional 修饰符(?)模型节点下,通过 required 字段列出该模型的所有必填属性的名称,未被列出的属性即为 optional
属性类型属性节点下,设置 type + format 可以标识属性的基本类型,如果是 schema 类型则用 $ref 字段表示,类型 union 则由扩展字段 x-kcl-types 来标识,此外,属性节点的 enum、pattern 也可以用于表示 KCL 类型。
KCL-OpenAPI 关于类型的对照关系,详见“基本数据类型”小节
属性默认值属性节点下,设置 default 字段即可为属性设置默认值

示例: 下例中 Pet 模型包含了 2 个属性:name(string 类型,必填属性,无注解,无默认值)、id(int64 类型,无注解,非必填,默认值为 -1)

# KCL schema Pet,包含两个属性 name 和 id
schema Pet:
name: str
id?: int = -1

# 对应的 OpenAPI 文档
{
"definitions": {
"Pet": {
"type": "object",
"properties": {
"name": {
"type": "string",
},
"id": {
"type": "integer",
"format": "int64",
"default": -1
}
},
"required": [
"name"
],
}
},
"swagger": "2.0",
"info": {
"title": "demo",
"version": "v1"
}
}

schema 索引签名

KCL schema 允许定义索引签名,用于定义属性名不固定的 dict,起到静态模板的作用。具体来说,KCL schema 索引签名包含如下几个元素:

  • 索引签名中 key 的类型:在方括号中声明,必须是基础类型
  • 索引签名中 value 的类型:在冒号后声明,可以是任意合法的 KCL 类型
  • 索引签名中的省略符:在方括号中,key 类型之前声明,使用"..."表示。如果带有该符号,表示该索引签名只用于约束未在 schema 中定义的属性;否则,表示 schema 中所有已定义和未定义属性都收到该索引签名的约束。
  • 索引签名中 key 的别名:在方括号中,紧随左方括号之后声明,使用名称 + 冒号表示,该别名可用于按名称引用索引签名
  • 索引签名的默认值:可以为索引签名设置默认值

在 OpenAPI 中,可以借助在模型节点的 additionalProperties 字段描述某些 key 为 string 的索引签名。但对于 KCL 索引签名中非 string 类型的 dict key、索引签名 key 的 check 校验,在 OpenAPI 规范没有对等的描述。它们与 OpenAPI 规范的对应关系如下:

KCL 索引签名元素OpenAPI 元素
索引签名中 key 的类型OpenAPI 仅支持 key 为 string 类型,无法自定义
索引签名中 value 的类型模型节点的下 additionalProperties 下的 "type" 字段
索引签名中的省略符OpenAPI 中表示索引签名时,只能表示 KCL 中带有省略符的情况
索引签名中 key 的别名OpenAPI 中不支持为索引签名定义 key 别名,(预计通过扩展支持:x-alias)
索引签名的默认值目前不支持

示例:下例中的 KCL schema Pet,包含两个预定义的属性 name 和 id,除此之外,还允许使用该 schema 的配置额外地赋值其他 key 为 string 类型,value 为 bool 类型的属性:

# KCL schema Pet,包含两个预定义的属性 name 和 id,允许额外给 key 为 string、value 为 bool 的属性赋值
schema Pet:
name: str
id?: int
[...str]: bool

# 对应的 OpenAPI 描述
{
"definitions": {
"Pet": {
"type": "object",
"properties": {
"name": {
"type": "string",
},
"id": {
"type": "integer",
"format": "int64",
}
},
"additionalProperties": {
"type": "bool"
},
"required": [
"name"
],
}
},
"swagger": "2.0",
"info": {
"title": "demo",
"version": "v1"
}
}

schema 继承关系

内联 schema

OpenAPI 支持嵌套地定义 schema,但 KCL 目前暂不支持 schema 的内联。OpenAPI 中内联定义的 schema 将被转换为 KCL 中带名称的 schema,其名称的命名规则为:在该内联 schema 的上层 schema 名称的基础上,增加相应的后缀。在拼接后缀时,根据定义了该内联 schema 的外层 OpenAPI 元素类型,后缀内容如下:

OpenAPI 文档中定义内联 schema 的元素KCL schema 名称拼接规则
某属性节点增加该属性节点的名称为后缀
AdditionalProperties 节点增加"AdditionalProperties"后缀

注:KCL 未来也可能会支持内联 schema,届时再更新这部分转换规则 示例 1:下例中的模型 Deployment 包含有 kind、spec 两个属性,其中 deploymentSpec 属性的 schema 通过内联的方式定义:

# OpenAPI 文档
{
"definitions": {
"Deployment": {
"type": "object",
"properties": {
"kind": {
"type": "string",
},
"spec": {
"type": "object",
"properties": {
"replicas": {
"type": "integer",
"format": "int64"
}
}
}
},
"required": [
"kind",
"spec"
],
}
},
"swagger": "2.0",
"info": {
"title": "demo",
"version": "v1"
}
}

# 转换为 KCL Schema 如下:
schema Deployment:
kind: str
spec: DeploymentSpec

schema DeploymentSpec:
replicas?: int

示例 2:下例中的模型 Person 中除固定属性 name 外,还允许包含额外的属性(additionalProperties),并且这部分额外属性的属性值的 schema 通过内联的方式定义:

# OpenAPI 文档
{
"definitions": {
"Person": {
"type": "object",
"properties": {
"name": {
"type": "string",
},
},
"required": [
"name",
"spec"
],
"additionalProperties": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
}
},
"required": [
"name"
]
},
}
},
"swagger": "2.0",
"info": {
"title": "demo",
"version": "v1"
}
}

# 转换为 KCL Schema 如下:
schema Person:
name: str
[...str]: [PersonAdditionalProperties]

schema PersonAdditionalProperties:
name: str
description?: str

KCL 文档

KCL doc 规范请参考:传送门 KCL 文档包含 module 文档、schema 文档两类,其中 schema 文档可以由 OpenAPI 转换得到。KCL schema 文档包含:

  • schema 描述信息:位于 schema 声明之后、schema 属性声明之前,是对 schema 的总体介绍
  • schema 属性信息:位于 shcema 描述信息之后,以 Attributes + 分割线分隔
  • schema 附加信息:位于 schema 属性信息之后,以 See Also + 分割线分隔
  • schema 示例信息:位于 schema 附加信息之后,以 Examples + 分割线分隔

它们与 OpenAPI 规范的对应关系如下:

KCL 文档元素OpenAPI 元素
schema 描述信息definitions 节点下,每个模型节点的 description 字段
schema 属性信息properties 节点下,每个属性节点的 description 字段
schema 附加信息definitions 节点下,每个模型节点的 example 字段
schema 示例信息definitions 节点下,每个模型节点的 externalDocs 字段

示例: 下例中为 Pet 模型定义了其 schema 描述文档 "The schema Pet definition";Pet 的两个属性 "name" 和 "id" 也分别定义了其属性文档 "The name of the pet" 及 "The id of the pet";Pet 的附加信息为 "Find more info here. https://petstore.swagger.io/";此外,Pet 模型还提供了模型实例的示例写法。

# KCL schema Pet,采用规范的 KCL 文档格式
schema Pet:
"""The schema Pet definition

Attributes
----------
name : str, default is Undefined, required
The name of the pet
id : int, default is -1, optional
The age of the pet

See Also
--------
Find more info here. https://petstore.swagger.io/

Examples
--------
pet = Pet {
name = "doggie"
id = 123
}
"""
name: str
id?: int = -1

# 对应的 OpenAPI 文档
{
"definitions": {
"Pet": {
"description": "The schema Pet definition",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the pet"
},
"id": {
"type": "integer",
"format": "int64",
"default": -1,
"description": "The age of the pet"
}
},
"required": [
"name"
],
"externalDocs": {
"description": "Find more info here",
"url": "https://petstore.swagger.io/"
},
"example": {
"name": "doggie",
"id": 123
}
}
},
"swagger": "2.0",
"info": {
"title": "demo",
"version": "v1"
}
}

基本数据类型

JSON Schema typeswagger typeKCL typecomment
booleanbooleanbool
numbernumberfloat
number format doubleunsupported
number format floatfloat
integerintegerint (32)
integer format int64unsupported
integer format int32int (32)
stringstringstr
string format bytestr
string format int-or-stringintstr
string format binaystr
string format dateunsupportedAs defined by full-date - RFC3339
string format date-timeunsupportedAs defined by date-time - RFC3339
string format passwordunsupportedfor swagger: A hint to UIs to obscure input.
datetimedatetime

Reference