You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置递归JSON Schema实现深层对象级联必填字段校验

递归JSON Schema实现深层对象的字段继承校验需求

需求与现有Schema

现有一个支持任意嵌套键的递归JSON Schema,基础结构如下:

{
  "type": "object",
  "properties": {
    "Age": {
      "type": "number"
    },
    "Name": {
      "type": "string"
    }
  },
  "patternProperties": {
    ".*": {
      "$ref": "#"
    }
  },
  "additionalProperties": false
}

当前Schema允许任意键映射到同结构的嵌套对象,但需要新增校验规则:每个最深层对象(即没有子对象的对象),必须自身包含Age和Name字段,或者其任意祖先对象包含这两个字段。

合法示例

{
  "level1": {
    "level2": {
      "Age": 20,
      "Name": "test"
    }
  }
}
{
  "level1": {
    "level2": {},
    "Age": 20
  },
  "Name": "test"
}
{
  "level1": {
    "level2": {
      "Age": 20
    }
  },
  "Name": "test"
}
{
  "level1": {
    "level2": {
      "Age": 20
    }
  },
  "level3": {
    "Age": 10
  },
  "Name": "test"
}

非法示例

{
  "level1": {
    "level2": {
      "Age": 20
    }
  },
  "level3": {
    "Name": "test2"
  },
  "Name": "test"
}

非法原因:level3对象自身没有Age,且其祖先(根对象)未提供Age,不满足校验规则。

实现方案

要实现该逻辑,需利用JSON Schema的$dynamicAnchor和$dynamicRef传递校验上下文——递归校验时需要跟踪祖先是否已提供Age和Name。以下是最终Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$dynamicAnchor": "node",
  "type": "object",
  "properties": {
    "Age": { "type": "number" },
    "Name": { "type": "string" }
  },
  "patternProperties": {
    ".*": {
      "$dynamicRef": "#node"
    }
  },
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "not": {
          "patternProperties": {
            ".*": { "type": "object" }
          },
          "minProperties": 1
        }
      },
      "then": {
        "anyOf": [
          { "required": ["Age", "Name"] },
          {
            "$dynamicRef": "#node",
            "required": ["Age"]
          },
          {
            "$dynamicRef": "#node",
            "required": ["Name"]
          }
        ]
      }
    },
    {
      "$dynamicAnchor": "node",
      "properties": {
        "Age": { "type": "number" },
        "Name": { "type": "string" }
      }
    }
  ]
}

方案说明

  1. 动态锚点传递上下文:$dynamicAnchor和$dynamicRef配合,让子对象递归校验时能继承父级是否已提供Age/Name的状态,替代传统$ref无法保留上下文的问题。
  2. 最深层对象判断:通过not+patternProperties+minProperties组合,判断当前对象是否没有任何子对象(即无匹配.*的键)。
  3. 最深层校验逻辑:
    • 要么自身同时包含Age和Name;
    • 要么通过$dynamicRef回溯祖先,确认祖先已提供这两个字段(动态锚点会保留父级的校验状态)。
  4. 上下文更新:若当前对象有Age或Name,动态锚点会更新上下文状态,子对象递归时可直接继承这些字段的存在性。

内容的提问来源于stack exchange,提问作者Kenji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:39:51