allOf案例

wen java案例 3

本文目录导读:

allOf案例

  1. 案例一:合并多个 Schema(最经典)
  2. 案例二:在子 Schema 中增加更严格的限制(条件细化)
  3. 案例三:与 if/then 配合实现复杂业务规则(进阶用法)
  4. 案例四:TS 类型中的 allOf 对应(组合类型)
  5. ⚠️ 注意事项(避坑指南)

在 JSON Schema 和 TypeScript 类型系统中,allOf 是一个非常核心的组合关键字,它的逻辑是:所有子 Schema 都必须同时满足(逻辑与)。

由于在 JSON Schema 中,我们无法直接在对象里写两个相同的键名(例如两个 properties),allOf 主要用于合并多个 Schema 约束

以下是几个最典型的应用场景案例:


合并多个 Schema(最经典)

场景:你有一个基础的“人”的 Schema,还有一个“员工”的 Schema,员工必须同时具备这两个特征。

{
  "allOf": [
    {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "age": { "type": "integer" }
      },
      "required": ["name"]
    },
    {
      "type": "object",
      "properties": {
        "employeeId": { "type": "string" },
        "department": { "type": "string" }
      },
      "required": ["employeeId"]
    }
  ]
}

校验结果

  • { "name": "张三", "employeeId": "E001" } (合法,两者都满足)
  • { "name": "张三" } (非法,缺少 employeeId
  • { "employeeId": "E001" } (非法,缺少 name

在子 Schema 中增加更严格的限制(条件细化)

场景:你有一个通用的“矩形”定义,但现在要求必须是“正方形”(长宽相等)。 痛点:你不能在一个 JSON 对象中写两个 properties 键。

{
  "allOf": [
    {
      "type": "object",
      "properties": {
        "width": { "type": "number" },
        "height": { "type": "number" }
      },
      "required": ["width", "height"]
    },
    {
      "properties": {
        "width": { "const": 10 },
        "height": { "const": 10 }
      }
    }
  ]
}

解析:第二个 Schema 相当于是在第一个 Schema 的基础上,强行将 widthheight 的值锁定为 10。 校验结果

  • { "width": 10, "height": 10 } (合法)
  • { "width": 5, "height": 5 } (不满足第二个 Schema 的 const 约束)

if/then 配合实现复杂业务规则(进阶用法)

场景:如果商品是“电子产品”,则必须提供“保修年限”;如果是“食品”,则必须提供“保质期”。

{
  "allOf": [
    {
      "type": "object",
      "properties": {
        "category": { "enum": ["electronics", "food"] },
        "name": { "type": "string" }
      },
      "required": ["category"]
    },
    {
      "if": {
        "properties": { "category": { "const": "electronics" } }
      },
      "then": {
        "required": ["warrantyYears"]
      }
    },
    {
      "if": {
        "properties": { "category": { "const": "food" } }
      },
      "then": {
        "required": ["expiryDate"]
      }
    }
  ]
}

解析allOf 确保第一个基础结构通过后,后面的两个 if 条件会依次判断。 校验结果

  • { "category": "electronics", "name": "手机", "warrantyYears": 2 }
  • { "category": "food", "name": "牛奶", "expiryDate": "2024-01-01" }
  • { "category": "electronics", "name": "手机" } (缺少 warrantyYears

TS 类型中的 allOf 对应(组合类型)

在 TypeScript 中使用 json-schema-to-ts 等库时,allOf 直接映射为交叉类型 &

type Schema = {
  allOf: [
    { properties: { a: { type: 'string' } } },
    { properties: { b: { type: 'number' } } }
  ]
}
// 解析出的 TS 类型为:
// { a: string } & { b: number }
// 等同于 { a: string; b: number }

⚠️ 注意事项(避坑指南)

  1. 不能覆盖,只能叠加allOf 不会像继承一样覆盖父类的属性,如果子 Schema 对 width 的限制是 type: 'string',而父 Schema 限制是 type: 'number',那么结果是 两者都要满足,即必须同时是字符串又得是数字(这不可能),会导致永远校验不通过
  2. 性能allOf 会遍历所有子 Schema,如果子 Schema 非常复杂且数量多,校验性能会下降,能只用 properties 解决的就别用 allOf
  3. 官方推荐:在 JSON Schema 官方文档中,对于“扩展对象”的场景,更推荐使用 unevaluatedProperties 或直接扩展,但在不支持的旧版(Draft-04/06)中,allOf 依然是主流方案。

如果你想了解特定场景(例如配合 $ref 引用外部 Schema)的案例,可以告诉我,我可以补充更复杂的嵌套例子。

抱歉,评论功能暂时关闭!