writing-openapi-specs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Writing OpenAPI Specs

编写OpenAPI规范

Reference for OpenAPI best practices and conventions. This skill provides guidance on taste, conventions, and grey areas not covered by the OpenAPI specification itself.
本内容是OpenAPI最佳实践与约定的参考资料,针对OpenAPI规范本身未涵盖的风格、约定及模糊领域提供指导。

When to Use This Skill

何时使用本指南

  • Writing a new OpenAPI specification
  • Improving operation naming and organization
  • Expressing complex data types (enums, polymorphism, nullable)
  • Handling file uploads, streaming, or server-sent events
  • Making specs more code-gen friendly
  • Understanding reusability patterns (components vs inline)
  • 编写新的OpenAPI规范
  • 优化操作命名与组织方式
  • 表达复杂数据类型(枚举、多态、可空类型)
  • 处理文件上传、流传输或Server-Sent Events
  • 让规范更适合代码生成
  • 理解复用模式(组件定义vs内联定义)

Core Principles

核心原则

Naming Conventions

命名约定

Operation IDs: Use lowercase with underscores, following
resource_action
pattern:
yaml
undefined
操作ID:使用小写加下划线的格式,遵循
resource_action
(资源_操作)的命名模式:
yaml
undefined

Good

推荐写法

operationId: users_list operationId: users_get operationId: users_create
operationId: users_list operationId: users_get operationId: users_create

Avoid

避免写法

operationId: GetApiV1Users # Auto-generated, not semantic

**Component Names**: Use PascalCase for schemas, parameters, and other reusable components:

```yaml
components:
  schemas:
    UserProfile:      # PascalCase
    OrderHistory:     # PascalCase
  parameters:
    PageLimit:        # PascalCase
Tags: Use lowercase with hyphens for machine-friendly tags:
yaml
tags:
  - name: user-management
    description: Operations for managing users
  - name: order-processing
    description: Operations for processing orders
For more details, see reference/operations.md and reference/components.md.
operationId: GetApiV1Users # 自动生成的命名,不具备语义性

**组件名称**:Schema、参数及其他可复用组件使用帕斯卡命名法(PascalCase):

```yaml
components:
  schemas:
    UserProfile:      # PascalCase
    OrderHistory:     # PascalCase
  parameters:
    PageLimit:        # PascalCase
标签:使用小写加连字符的格式,便于机器识别:
yaml
tags:
  - name: user-management
    description: Operations for managing users
  - name: order-processing
    description: Operations for processing orders
更多细节请参考reference/operations.mdreference/components.md

Documentation Standards

文档标准

Use CommonMark: All
description
fields support CommonMark syntax for rich formatting:
yaml
description: |
  Retrieves a user by ID.

  ## Authorization
  Requires `users:read` scope.

  ## Rate Limits
  - 100 requests per minute per API key
  - 1000 requests per hour per IP
Be Specific: Provide actionable information, not generic descriptions:
yaml
undefined
使用CommonMark:所有
description
字段支持CommonMark语法,用于实现富文本格式:
yaml
description: |
  根据ID获取用户信息。

  ## 授权要求
  需要`users:read`权限范围。

  ## 速率限制
  - 每个API密钥每分钟最多100次请求
  - 每个IP每小时最多1000次请求
内容具体:提供可落地的信息,避免通用化描述:
yaml
undefined

Good

推荐写法

description: Returns a paginated list of active users, ordered by creation date (newest first)
description: 返回按创建时间倒序排列的活跃用户分页列表(最新的在前)

Avoid

避免写法

description: Gets users

**Use `examples` over `example`**: The plural `examples` field provides better SDK generation:

```yaml
description: 获取用户

**使用`examples`而非`example`**:复数形式的`examples`字段更利于SDK生成:

```yaml

Good

推荐写法

examples: basic_user: value: id: 123 name: "John Doe" admin_user: value: id: 456 name: "Jane Admin" role: admin
examples: basic_user: value: id: 123 name: "John Doe" admin_user: value: id: 456 name: "Jane Admin" role: admin

Avoid single example

避免单一示例写法

example: id: 123 name: "John Doe"

For more details, see [reference/examples.md](reference/examples.md).
example: id: 123 name: "John Doe"

更多细节请参考[reference/examples.md](reference/examples.md)。

Reusability

复用原则

Create components for:
  • Schemas used in multiple operations
  • Common parameters (pagination, filtering)
  • Common responses (errors, success patterns)
  • Security schemes
Keep inline for:
  • Operation-specific request bodies
  • Unique response shapes
  • One-off parameters
yaml
undefined
以下场景建议创建组件
  • 多个操作中复用的Schema
  • 通用参数(分页、过滤)
  • 通用响应(错误、成功模式)
  • 安全认证方案
以下场景建议内联定义
  • 操作专属的请求体
  • 唯一的响应结构
  • 一次性使用的参数
yaml
undefined

Reusable schema

可复用Schema

components: schemas: User: type: object properties: id: {type: integer} name: {type: string}
components: schemas: User: type: object properties: id: {type: integer} name: {type: string}

Reference it

引用组件

paths: /users/{id}: get: responses: '200': content: application/json: schema: $ref: '#/components/schemas/User'

For more details, see [reference/components.md](reference/components.md).
paths: /users/{id}: get: responses: '200': content: application/json: schema: $ref: '#/components/schemas/User'

更多细节请参考[reference/components.md](reference/components.md)。

Complex Patterns Quick Reference

复杂模式速查

These patterns are commonly challenging. Brief examples below with links to detailed guidance.
这些模式通常是难点,以下是简要示例及详细指南链接。

Enums

枚举

Use string enums with clear, semantic values:
yaml
type: string
enum:
  - pending
  - approved
  - rejected
  - cancelled
Avoid:
  • Numeric strings ("0", "1", "2")
  • Generic values ("value1", "value2")
  • Unclear abbreviations ("pnd", "appr")
See reference/schemas.md#enums for more.
使用语义清晰的字符串枚举:
yaml
type: string
enum:
  - pending
  - approved
  - rejected
  - cancelled
避免
  • 数字字符串("0", "1", "2")
  • 通用值("value1", "value2")
  • 含义模糊的缩写("pnd", "appr")
更多内容请参考reference/schemas.md#enums

Polymorphism (oneOf/allOf/anyOf)

多态(oneOf/allOf/anyOf)

oneOf: Value matches exactly one schema (type discrimination)
yaml
PaymentMethod:
  oneOf:
    - $ref: '#/components/schemas/CreditCard'
    - $ref: '#/components/schemas/BankAccount'
    - $ref: '#/components/schemas/PayPal'
  discriminator:
    propertyName: type
    mapping:
      credit_card: '#/components/schemas/CreditCard'
      bank_account: '#/components/schemas/BankAccount'
      paypal: '#/components/schemas/PayPal'
allOf: Value matches all schemas (composition/inheritance)
yaml
AdminUser:
  allOf:
    - $ref: '#/components/schemas/User'
    - type: object
      properties:
        permissions:
          type: array
          items: {type: string}
anyOf: Value matches one or more schemas (flexible union)
yaml
SearchFilter:
  anyOf:
    - $ref: '#/components/schemas/TextFilter'
    - $ref: '#/components/schemas/DateFilter'
    - $ref: '#/components/schemas/NumericFilter'
See reference/schemas.md#polymorphism for detailed guidance.
oneOf:值精确匹配其中一个Schema(类型区分)
yaml
PaymentMethod:
  oneOf:
    - $ref: '#/components/schemas/CreditCard'
    - $ref: '#/components/schemas/BankAccount'
    - $ref: '#/components/schemas/PayPal'
  discriminator:
    propertyName: type
    mapping:
      credit_card: '#/components/schemas/CreditCard'
      bank_account: '#/components/schemas/BankAccount'
      paypal: '#/components/schemas/PayPal'
allOf:值匹配所有Schema(组合/继承)
yaml
AdminUser:
  allOf:
    - $ref: '#/components/schemas/User'
    - type: object
      properties:
        permissions:
          type: array
          items: {type: string}
anyOf:值匹配一个或多个Schema(灵活联合类型)
yaml
SearchFilter:
  anyOf:
    - $ref: '#/components/schemas/TextFilter'
    - $ref: '#/components/schemas/DateFilter'
    - $ref: '#/components/schemas/NumericFilter'
更多内容请参考reference/schemas.md#polymorphism

Discriminators

区分器

Use discriminators with
oneOf
for efficient type identification:
yaml
Pet:
  oneOf:
    - $ref: '#/components/schemas/Dog'
    - $ref: '#/components/schemas/Cat'
  discriminator:
    propertyName: petType
    mapping:
      dog: '#/components/schemas/Dog'
      cat: '#/components/schemas/Cat'

Dog:
  type: object
  required: [petType, bark]
  properties:
    petType:
      type: string
      enum: [dog]
    bark:
      type: string

Cat:
  type: object
  required: [petType, meow]
  properties:
    petType:
      type: string
      enum: [cat]
    meow:
      type: string
See reference/schemas.md#discriminators for more.
结合
oneOf
使用区分器,实现高效的类型识别:
yaml
Pet:
  oneOf:
    - $ref: '#/components/schemas/Dog'
    - $ref: '#/components/schemas/Cat'
  discriminator:
    propertyName: petType
    mapping:
      dog: '#/components/schemas/Dog'
      cat: '#/components/schemas/Cat'

Dog:
  type: object
  required: [petType, bark]
  properties:
    petType:
      type: string
      enum: [dog]
    bark:
      type: string

Cat:
  type: object
  required: [petType, meow]
  properties:
    petType:
      type: string
      enum: [cat]
    meow:
      type: string
更多内容请参考reference/schemas.md#discriminators

Nullable Types

可空类型

Handle null values differently based on OpenAPI version:
OpenAPI 3.1 (JSON Schema 2020-12 compliant):
yaml
type: [string, "null"]
根据OpenAPI版本不同,处理空值的方式有所区别:
OpenAPI 3.1(兼容JSON Schema 2020-12):
yaml
type: [string, "null"]

or

type: string nullable: true # Still supported for compatibility

**OpenAPI 3.0**:
```yaml
type: string
nullable: true
For optional fields, use
required
array:
yaml
type: object
properties:
  name: {type: string}      # Can be omitted
  email: {type: string}     # Can be omitted
required: [name]            # email is optional
See reference/schemas.md#nullable for more.
type: string nullable: true # 为兼容仍支持该写法

**OpenAPI 3.0**:
```yaml
type: string
nullable: true
对于可选字段,使用
required
数组定义:
yaml
type: object
properties:
  name: {type: string}      # 可省略
  email: {type: string}     # 可省略
required: [name]            # email为可选字段
更多内容请参考reference/schemas.md#nullable

File Uploads

文件上传

Use
multipart/form-data
for file uploads:
yaml
requestBody:
  required: true
  content:
    multipart/form-data:
      schema:
        type: object
        properties:
          file:
            type: string
            format: binary
          metadata:
            type: object
            properties:
              description: {type: string}
              tags:
                type: array
                items: {type: string}
        required: [file]
For base64-encoded files in JSON:
yaml
requestBody:
  content:
    application/json:
      schema:
        type: object
        properties:
          filename: {type: string}
          content:
            type: string
            format: byte  # base64-encoded
See reference/request-bodies.md#file-uploads for more.
使用
multipart/form-data
处理文件上传:
yaml
requestBody:
  required: true
  content:
    multipart/form-data:
      schema:
        type: object
        properties:
          file:
            type: string
            format: binary
          metadata:
            type: object
            properties:
              description: {type: string}
              tags:
                type: array
                items: {type: string}
        required: [file]
对于JSON中的Base64编码文件:
yaml
requestBody:
  content:
    application/json:
      schema:
        type: object
        properties:
          filename: {type: string}
          content:
            type: string
            format: byte  # Base64编码
更多内容请参考reference/request-bodies.md#file-uploads

Server-Sent Events (SSE)

Server-Sent Events (SSE)

Express streaming responses with
text/event-stream
:
yaml
responses:
  '200':
    description: Stream of events
    content:
      text/event-stream:
        schema:
          type: string
          description: |
            Server-sent events stream. Each event follows the format:

            ```
            event: message
            data: {"type": "update", "content": "..."}

            ```
        examples:
          notification_stream:
            value: |
              event: message
              data: {"type": "notification", "message": "New order received"}

              event: message
              data: {"type": "notification", "message": "Order processing complete"}
See reference/responses.md#streaming for more patterns.
使用
text/event-stream
定义流响应:
yaml
responses:
  '200':
    description: 事件流
    content:
      text/event-stream:
        schema:
          type: string
          description: |
            Server-Sent Events流。每个事件遵循以下格式:

            ```
            event: message
            data: {"type": "update", "content": "..."}

            ```
        examples:
          notification_stream:
            value: |
              event: message
              data: {"type": "notification", "message": "收到新订单"}

              event: message
              data: {"type": "notification", "message": "订单处理完成"}
更多模式请参考reference/responses.md#streaming

Field Reference

字段参考

Detailed guidance for each major OpenAPI field:
  • Operations: Operation IDs, methods, tags, deprecation → reference/operations.md
  • Schemas: Data types, polymorphism, enums, nullable → reference/schemas.md
  • Parameters: Path, query, header, cookie parameters → reference/parameters.md
  • Request Bodies: Content types, file uploads, encoding → reference/request-bodies.md
  • Responses: Status codes, streaming, error patterns → reference/responses.md
  • Components: Reusable definitions, organization → reference/components.md
  • Security: Authentication schemes, scopes, granular control → reference/security.md
  • Examples: Single and multiple examples, placement → reference/examples.md
各主要OpenAPI字段的详细指导:
  • 操作:操作ID、请求方法、标签、弃用规则 → reference/operations.md
  • Schema:数据类型、多态、枚举、可空类型 → reference/schemas.md
  • 参数:路径参数、查询参数、头部参数、Cookie参数 → reference/parameters.md
  • 请求体:内容类型、文件上传、编码方式 → reference/request-bodies.md
  • 响应:状态码、流传输、错误模式 → reference/responses.md
  • 组件:可复用定义、组织方式 → reference/components.md
  • 安全:认证方案、权限范围、细粒度控制 → reference/security.md
  • 示例:单示例与多示例、示例位置 → reference/examples.md

SDK Generation Considerations

SDK生成注意事项

When writing specs for SDK generation:
  1. Always define
    operationId
    : Required for meaningful method names
  2. Provide rich examples: Helps generate better documentation and tests
  3. Be explicit about required fields: Affects SDK method signatures
  4. Use discriminators with oneOf: Generates type-safe unions
  5. Document error responses: Generates better error handling code
Example SDK-friendly operation:
yaml
paths:
  /users:
    get:
      operationId: users_list
      summary: List all users
      description: Returns a paginated list of users
      parameters:
        - name: limit
          in: query
          schema: {type: integer, default: 20}
        - name: offset
          in: query
          schema: {type: integer, default: 0}
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                required: [data, pagination]
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  pagination:
                    $ref: '#/components/schemas/PaginationInfo'
              examples:
                success:
                  value:
                    data: [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]
                    pagination: {total: 100, limit: 20, offset: 0}
This generates:
sdk.users.list({limit: 20, offset: 0})
编写用于SDK生成的规范时:
  1. 务必定义
    operationId
    :这是生成有意义方法名的必要条件
  2. 提供丰富的示例:有助于生成更优质的文档与测试用例
  3. 明确必填字段:会影响SDK的方法签名
  4. 结合oneOf使用区分器:生成类型安全的联合类型
  5. 文档化错误响应:生成更完善的错误处理代码
适合SDK生成的操作示例:
yaml
paths:
  /users:
    get:
      operationId: users_list
      summary: 获取所有用户列表
      description: 返回用户的分页列表
      parameters:
        - name: limit
          in: query
          schema: {type: integer, default: 20}
        - name: offset
          in: query
          schema: {type: integer, default: 0}
      responses:
        '200':
          description: 请求成功
          content:
            application/json:
              schema:
                type: object
                required: [data, pagination]
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  pagination:
                    $ref: '#/components/schemas/PaginationInfo'
              examples:
                success:
                  value:
                    data: [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]
                    pagination: {total: 100, limit: 20, offset: 0}
该规范会生成:
sdk.users.list({limit: 20, offset: 0})

Common Pitfalls

常见误区

Don't:
  • Use generic descriptions like "Gets data" or "Returns object"
  • Mix naming conventions (pick one style and stick to it)
  • Forget
    operationId
    (causes auto-generated names)
  • Use
    example
    when you mean
    examples
    (plural is better)
  • Make everything required (be thoughtful about optional fields)
  • Inline everything (use components for reusability)
  • Reference everything (inline simple one-off schemas)
  • Forget to document error responses
  • Use magic numbers without explanation
  • Omit content types (be explicit)
Do:
  • Provide actionable, specific descriptions
  • Use consistent naming patterns throughout
  • Define clear
    operationId
    for every operation
  • Use
    examples
    (plural) with named examples
  • Carefully consider required vs optional fields
  • Balance reusability with clarity
  • Document all expected responses (success and errors)
  • Explain constraints and validation rules
  • Be explicit about content types and formats
请勿
  • 使用诸如"获取数据"或"返回对象"这类通用描述
  • 混合使用多种命名约定(选定一种风格并保持一致)
  • 遗漏
    operationId
    (会导致自动生成无意义的名称)
  • 在应该用
    examples
    时使用
    example
    (复数形式更优)
  • 将所有字段设为必填(谨慎区分必填与可选字段)
  • 所有内容都内联定义(使用组件实现复用)
  • 所有内容都引用组件(简单的一次性Schema直接内联)
  • 遗漏错误响应的文档
  • 使用未说明含义的魔法数值
  • 省略内容类型(明确指定)
建议
  • 提供具体、可落地的描述
  • 全程使用一致的命名模式
  • 为每个操作定义清晰的
    operationId
  • 使用带命名的
    examples
    (复数形式)
  • 仔细区分必填与可选字段
  • 在复用性与可读性之间取得平衡
  • 文档化所有预期响应(成功与错误)
  • 说明约束条件与验证规则
  • 明确指定内容类型与格式