理解 OpenAPI 中的 oneOf(避免困惑)

发布: (2025年12月23日 GMT+8 15:00)
3 min read
原文: Dev.to

Source: Dev.to

Introduction

在使用 OpenAPI 设计 API 时,oneOf 常常显得令人生畏。它功能强大,但容易被误用——尤其是在 PATCH 接口中。下面我们用简单的方式把它拆解说明。

What oneOf Means in OpenAPI (JSON Schema)

  • 请求体 必须完全匹配 列表中的 一个 schema。
  • 不能为零。
  • 必须恰好一个。

Example

schema:
  oneOf:
    - $ref: '#/components/schemas/InverterPatch'
    - $ref: '#/components/schemas/EVPatch'
    - $ref: '#/components/schemas/EVCSPatch'

这告诉 OpenAPI:“负载必须符合上述 恰好一个 schema。”

oneOf Is Tricky with PATCH

PATCH 请求是部分更新。客户端通常只发送少量字段。

想象下面的负载:

{
  "reverseFlow": true
}

如果 reverseFlow 同时出现在 InverterPatchEVCSPatch 中,负载就会匹配 多个 schema。

🚫 结果: 验证失败,因为 oneOf 要求恰好匹配一个。

Using a Discriminator to Resolve Ambiguity

discriminator:
  propertyName: type

此时客户端发送:

{
  "type": "inverter",
  "reverseFlow": true
}

OpenAPI 能立即知道:

  • type = inverter → 使用 InverterPatch → 验证成功。

💡 discriminator 告诉 OpenAPI 应该使用哪个 schema 进行验证。

When to Use oneOf (with a Discriminator)

  • 你有多个 schema。
  • 某些字段会重叠。
  • 客户端可能发送部分更新。
  • 你希望在 OpenAPI 层面进行验证,而不是仅靠后端逻辑。

When to Avoid oneOf

  • 你不需要 OpenAPI 在 schema 之间做选择。
  • 后端已经知道资源类型。
  • 你可以在运行时对特定类型的规则进行验证。

在这些情况下,使用一个包含可选字段的单一 PATCH schema 更简单,也往往更合适。

Summary

  • oneOf = 必须恰好匹配一个 schema。
  • 字段重叠 + PATCH = 歧义。
  • discriminator 能消除这种歧义。
  • 除非真的需要在 schema 之间进行选择,否则不要使用 oneOf

正确使用 oneOf 能让你的 API 更安全、更具自我文档化;使用不当,则会让 PATCH 接口变得痛苦。

Back to Blog

相关文章

阅读更多 »

介绍 graphql-complexity-validation

✨ 特性 - 零运行时依赖 - 完全类型化的 TypeScript - 支持 fragments 与 inline fragments - 默认忽略 Introspection 适用于: - Apollo…