API 契约核心元素:接口标识、请求响应结构、数据模型定义

模块边界一旦划清,两侧便通过 API 契约 建立双向承诺。契约由三个不可分割的元素组成:接口标识(谁在哪儿)、请求响应结构(怎么传、传什么)、数据模型定义(长什么样、有哪些约束)。三者共同构成一次可验证、可测试、可文档化的交互单元。

2.1 接口标识

接口标识是契约的入口,它必须唯一锁定一个操作。在实际落地中,标识由以下维度组合而成:

维度说明典型示例
路径 / 资源RESTful 资源路径或 RPC 服务名+方法/api/v2/orders/{orderId}
HTTP 方法操作语义(GET/POST/PUT/DELETE)PUT
版本标识路径前缀或 Header 中携带Accept: application/vnd.company.v2+json
额外作用域地域、租户、环境等X-Region: us-east-1
实践要点: 接口标识应做到“一眼可读”——不看文档也大致知道这个接口要操作什么资源、用什么动作。避免使用模糊动词加名词的拼接,如 /doProcess 就远不如 /orders/{orderId}/submit 清晰。

2.2 请求响应结构

结构规定了数据如何包装、如何传递、如何结束。常见分层如下:

  • Headers:认证令牌、内容类型、跟踪 ID、速率限制指示等。
  • Body:业务数据载体,JSON/Protobuf 序列化后传输。
  • HTTP 状态码:最简洁的响应语义(200 成功,400 参数错误,500 内部错误)。
  • 错误体规范:当状态码非 2xx 时,body 内的结构化错误信息(code/message/details)。

下面是请求和响应的精简契约示例(YAML):

# 请求契约
paths:
  /api/v2/orders:
    post:
      operationId: createOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
      responses:
        '201':
          description: 订单创建成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '400':
          description: 参数校验失败
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

2.3 数据模型定义

数据模型是所有结构的基石。它不仅要描述字段类型,还要声明约束、可选性、组合关系。典型建模要素如下:

要素作用示例(JSON Schema)
类型与格式基础类型 + 扩展格式"type": "string", "format": "date-time"
必须/可选标记必填字段"required": ["orderId", "amount"]
枚举与约束限定取值范围"enum": ["pending", "confirmed"], "minimum": 0
嵌套与引用避免扁平化,利用 $ref 复用"items": {"$ref": "#/definitions/LineItem"}
建模黄金法则: 数据模型一旦发布,基本只增不减。请在设计阶段就考虑未来扩展:使用 map 结构、预留 extensions 字段、用 oneOf 处理多态。避免在早期就钉死父类继承。

2.4 三元素关系图

下面的 SVG 展示了三个核心元素如何围绕一次完整的 API 交互协同:

API 契约三元素关系图 接口标识 请求结构 响应结构 数据模型定义 约束与验证(类型、范围、枚举、必填) 箭头方向:请求/响应通过接口标识识别,接口标识引用数据模型,所有元素最终由约束与验证统一兜底
常见陷阱: 很多团队过早陷入数据结构细节而忽略接口标识的稳定性——结果接口路径设计粗糙,后期版本迭代时被迫重写所有客户端。务必先稳定标识(尤其是路径和版本策略),再深化请求响应结构,最后填充数据模型。顺序颠倒将导致大规模返工。