如何在 Apifox 中使用 OpenAPI 的 discriminator?

如何在 Apifox 中使用 OpenAPI 的 discriminator?

我们在往期文章《API 文档中有多种参数结构怎么办?》里讲到过,如果 API 文档中需要用到多种参数结构,那么可以在 Apifox 中使用oneOfanyOfallOf 来处理。

在使用这些“组合模式”定义了多种参数结构后,如果参数中有用于标识类型的字段,并且你希望让文档更直观一些,那么可以选择使用 OpenAPI 规范里的discriminator 来进一步区分结构。

什么是 discriminator

在 OpenAPI 中,discriminator 的作用是实现面向对象编程中的“多态性”。

简单来说,它通过一个共享的属性及其唯一的值,来明确指出在 oneOfanyOf 列表中到底应该使用哪一个具体的 Schema。

比如在宠物商店中,我们需要用一个数据模型来描述宠物,但是猫、狗有不同的属性。

狗的数据结构:

{
  "name": "旺财",
  "age": 3,
  "weight": 25.5,
  "petType": "dog",
  "breed": "金毛",
  "isVaccinated": true,
  "walkingSchedule": "早与晚",
  "favoriteToys": ["飞盘","网球"],
  "trainingLevel": "中级"
}


猫的数据结构:

{
  "name": "喵",
  "age": 2,
  "weight": 4.2,
  "petType": "cat",
  "isVaccinated": true,
  "isIndoor": true,
  "litterBoxType": "封闭式",
  "scratchingPostHeight": 120,
  "favoriteSleepingSpot": "阳台"
}


可以看出,虽然都有 petTypenameage 等共同字段,但狗有特有的 breedwalkingSchedule 等字段,猫有特有的 isIndoorlitterBoxType 等字段。

如果在设计 API 文档时仅通过oneOf来定义多个结构,文档上虽然能区分出 DogCat 两个 Schema,但每种类型的对应关系并不够直观,读者需要在两个 Schema 标签页之间来回切换对比,参数多的话读起来容易困惑。

什么是 discriminator


而通过设置 discriminator,在文档展示时,它会直接提供一个下拉菜单,让读者可以选择 petType 的值(dogcat),页面会自动展示对应的数据结构。这样就不需要反复比对,也更容易理解整个数据模型的关系,如下图所示:

在 Apifox 里使用 discriminator



discriminator 通常与 oneOfanyOf 配合使用。oneOf 定义了对象可能的几种结构,而 discriminator 则告诉解析器如何根据数据内容快速确定应该选用哪一个 Schema。

这样可以让复杂对象的定义更清晰,也能帮助工具在渲染文档或生成代码时自动区分类型。

discriminator 的配置属性

discriminator 包含两个关键属性:

  • propertyName:指定用于区分类型的字段名称,例如上例中的 petType
  • mapping:定义字段值与具体 Schema 的映射关系,比如 "dog" 对应狗的 Schema,"cat" 对应猫的 Schema

在 OpenAPI 中的配置示例如下:

discriminator:
  propertyName: petType
  mapping:
    dog: '#/components/schemas/Dog'
    cat: '#/components/schemas/Cat'


在 Apifox 中配置 discriminator

在 Apifox 中设置 discriminator 有两种方式:界面配置结合 JSON Schema,或直接导入 OpenAPI 文件。

界面配置结合 JSON Schema

首先在 Apifox 中创建好对应的数据模型,例如创建 DogCat 两个数据模型:

在 Apifox 中配置 discriminator


打开需要使用这些数据模型的接口,进入请求体或响应体编辑页面。选择要定义为“组合模式”的字段,点击“高级设置 -> 组合模式 -> oneOf"。

界面配置结合 JSON Schema


oneOf 中引用你需要组合的数据模型,例如 DogCat

在 oneOf 中引用你需要组合的数据模型


现在已经通过 oneOf 定义了多种可能的结构,接下来需要添加 discriminator 来指定如何区分这些结构。点击 JSON Schema 切换到代码模式:

在 Apifox 中添加 discriminator 来指定如何区分结构


在适当的位置添加 discriminator 配置(与 oneOf 同级),例如:

"discriminator": {
    "propertyName": "petType",
    "mapping": {
        "dog": "#/definitions/190704823",
        "cat": "#/definitions/190704706"
    }
}


mapping 中的值,如 #/definitions/190704823,是 Apifox 内部为数据模型生成的唯一 ID,你可以在 JSON Schema 配置面板中,找到每个数据模型对应的这个 definitions 路径。

Apifox 内部为数据模型生成的唯一 ID


配置完成后保存,在 API 文档里,就可以根据 petType 字段的值智能切换对象类型了。

在 Apifox 中配置 discriminator 完成


通过导入 OpenAPI 文件

这是更标准的方式,尤其适合习惯“规范先行”的团队。

你只需直接编写包含 discriminator 的标准 OpenAPI 文件,然后导入到 Apifox 中。

在 OpenAPI 文件中,discriminator 的定义如下:

Pet:
  oneOf:
    - $ref: '#/components/schemas/Dog'
    - $ref: '#/components/schemas/Cat'
  discriminator:
    propertyName: petType
    mapping:
      dog: '#/components/schemas/Dog'
      cat: '#/components/schemas/Cat'

这个定义明确了:

  • 通过 oneOf 指定对象可能是 DogCat 类型
  • 通过 discriminator 指定根据 petType 字段的值来确定具体类型
  • 通过 mapping 明确 "dog" 对应 Dog Schema,"cat" 对应 Cat Schema。

完整的 OpenAPI 定义如下:

openapi: 3.0.3
info:
  title: Pet Shop API
  version: 1.0.0

components:
  schemas:
    Dog:
      type: object
      properties:
        petType:
          type: string
          enum: [dog]
        name:
          type: string
        age:
          type: integer
        weight:
          type: number
        breed:
          type: string
        isVaccinated:
          type: boolean
        walkingSchedule:
          type: string
        favoriteToys:
          type: array
          items:
            type: string
        trainingLevel:
          type: string
      required:
        - petType
        - name
        - age

    Cat:
      type: object
      properties:
        petType:
          type: string
          enum: [cat]
        name:
          type: string
        age:
          type: integer
        weight:
          type: number
        isVaccinated:
          type: boolean
        isIndoor:
          type: boolean
        litterBoxType:
          type: string
        scratchingPostHeight:
          type: integer
        favoriteSleepingSpot:
          type: string
      required:
        - petType
        - name
        - age

    Pet:
      oneOf:
        - $ref: '#/components/schemas/Dog'
        - $ref: '#/components/schemas/Cat'
      discriminator:
        propertyName: petType
        mapping:
          dog: '#/components/schemas/Dog'
          cat: '#/components/schemas/Cat'

paths:
  /pets:
    get:
      summary: Get pet information
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'


编写或生成完整的 OpenAPI 文件后,在 Apifox 中选择导入功能。Apifox 会解析文件中的所有定义,自动创建对应的数据模型和接口,同时正确识别 discriminator 配置(这里加上了枚举来锁定参数值)。

在 Apifox 中导入OpenAPI 文件并识别 discriminator 配置



常见问题

Q:什么时候用 discriminator

discriminator 的使用前提是你的接口数据中已经有一个用来标识类型的字段。上面例子中的 petType 字段是接口设计时就存在的,用来区分不同类型的宠物。

discriminator 只是告诉 API 文档工具,可以根据这个 petType 字段的值来判断数据结构。

如果你的接口数据中没有这样的区分字段,那就不适合用 discriminator,直接用 oneOf 就够了。

如果结构简单、类型不多,也不一定非要用 discriminator

Q:discriminator 一定要配 oneOf 吗

是的,必须和 oneOf、anyOf 或 allOf 结合使用。它本身不能单独定义数据结构,只是用来指定如何在多种可能的结构中进行区分。




discriminator 是 OpenAPI 规范中的一个可选功能,用来增强 oneOf/anyOf/allOf 的使用体验。
当你的接口数据中已经包含用于标识类型的字段时,可以通过在 Apifox 中配置 discriminator,来让 API 文档更清晰、更智能。
当然,如果你觉得配置麻烦,或者数据结构相对简单,完全可以只使用 oneOf 等组合模式。

欢迎各位用户对 Apifox 继续提出使用反馈和优化意见,我们会持续优化更新,致力于为用户提供更优秀的产品功能和更极致的使用体验!

有任何问题欢迎在 Apifox 用户群与我们交流沟通
订阅
qrcode

订阅

随时随地获取 Apifox 最新动态