You need to enable JavaScript to run this app. 面向切面结构的JSON如何编写对应JSON Schema完成校验
优惠活动
大模型
产品
解决方案
定价
更多

面向切面结构的JSON如何编写对应JSON Schema完成校验

你之前写的Schema用了元组形式的items配置,这类配置只会校验数组对应位置的元素,不会强制要求数组包含所有必填项,也不会限制数组最小长度,所以才会出现空数组、缺必填项也能通过校验的问题,另外你还把metadata键名误写为驼峰的metaData,也会导致匹配失效。

以下是两种可行的校验方案:

方案一:用Draft 2019-09的contains关键字实现(无需大量if/then)

这个方案支持元素任意顺序,不需要写复杂的条件判断,只要你的校验器支持JSON Schema Draft 2019-09及以上版本(目前主流校验器如Ajv、Hyperjump都支持)就可以用。

核心逻辑是:

  • 强制数组必须恰好包含1次nv、metadata、status三类对象
  • 所有额外的元素必须是你预定义的动态键对象(nodes/edges等)
  • 如果需要严格匹配metadata里声明的name,可结合$data扩展(Ajv支持)实现完全动态校验,不需要提前写死条件

示例Schema如下:

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "type": "array",
  "minItems": 3,
  "allOf": [
    // 强制必须存在1个nv对象
    {
      "contains": {
        "type": "object",
        "properties": {
          "nv": {
            "type": "array",
            "items": { "$ref": "#/$defs/nv" }
          }
        },
        "required": ["nv"],
        "additionalProperties": false
      },
      "minContains": 1,
      "maxContains": 1
    },
    // 强制必须存在1个metadata对象
    {
      "contains": {
        "type": "object",
        "properties": {
          "metadata": {
            "type": "array",
            "items": { "$ref": "#/$defs/metadataItem" }
          }
        },
        "required": ["metadata"],
        "additionalProperties": false
      },
      "minContains": 1,
      "maxContains": 1
    },
    // 强制必须存在1个status对象
    {
      "contains": {
        "type": "object",
        "properties": {
          "status": {
            "type": "array",
            "items": { "$ref": "#/$defs/status" }
          }
        },
        "required": ["status"],
        "additionalProperties": false
      },
      "minContains": 1,
      "maxContains": 1
    }
  ],
  // 所有元素都必须属于以下允许的类型
  "items": {
    "type": "object",
    "oneOf": [
      {
        "properties": {"nv": {"type": "array", "items": { "$ref": "#/$defs/nv" }}},
        "required": ["nv"]
      },
      {
        "properties": {"metadata": {"type": "array", "items": { "$ref": "#/$defs/metadataItem" }}},
        "required": ["metadata"]
      },
      {
        "properties": {"status": {"type": "array", "items": { "$ref": "#/$defs/status" }}},
        "required": ["status"]
      },
      // 下面是所有允许的动态键
      {
        "properties": {"nodes": {"type": "array", "items": { "$ref": "#/$defs/nodes" }}},
        "required": ["nodes"]
      },
      {
        "properties": {"edges": {"type": "array", "items": { "$ref": "#/$defs/edges" }}},
        "required": ["edges"]
      },
      {
        "properties": {"nodeAttribute": {"type": "array", "items": { "$ref": "#/$defs/nodeAttribute" }}},
        "required": ["nodeAttribute"]
      },
      {
        "properties": {"edgeAttribute": {"type": "array", "items": { "$ref": "#/$defs/edgeAttribute" }}},
        "required": ["edgeAttribute"]
      }
    ],
    "additionalProperties": false
  },
  "$defs": {
    "nv": {
      "type": "object",
      "properties": {"ln": {"type": "number"}},
      "required": ["ln"]
    },
    "metadataItem": {
      "type": "object",
      "properties": {"name": {"type": "string"}},
      "required": ["name"]
    },
    "status": {
      "type": "object",
      "properties": {"success": {"type": "boolean"}},
      "required": ["success"]
    },
    "nodes": { /* 你的nodes结构定义 */ },
    "edges": { /* 你的edges结构定义 */ },
    "nodeAttribute": { /* 你的nodeAttribute结构定义 */ },
    "edgeAttribute": { /* 你的edgeAttribute结构定义 */ }
  }
}

如果要实现和metadata声明的name完全匹配(比如metadata里写了3个name,就必须有3个对应键的对象),只要你用的校验器支持$data扩展,在上面的Schema里加几个规则就可以,不需要修改其他逻辑。

方案二:用if/then/else实现标准JSON Schema兼容方案

如果你需要兼容更低版本的JSON Schema,或者不能用$data扩展,也可以用if/then/else实现:
每个可能的name字段值对应一条规则,示例如下:

{
  // 上面的基础规则不变,新增规则加在allOf数组里
  "allOf": [
    // 原来的三个contains规则保留,加下面的条件
    {
      "if": {
        "items": {
          "properties": {
            "metadata": {
              "contains": {"properties": {"name": {"const": "nodes"}}},
              "minContains": 1
            }
          }
        }
      },
      "then": {
        "contains": {
          "properties": {"nodes": {}},
          "required": ["nodes"]
        },
        "minContains":1,
        "maxContains":1
      }
    },
    // 每个可能的name都按上面的格式加一条规则即可
  ]
}

即使metadata的条目多,每条规则的结构都是固定的,批量生成也很方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 02:45:05