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

能否在JSON Schema的if逻辑中修改$defs定义?

多语言翻译字段的JSON Schema条件验证复用问题

我需要为包含多语言翻译字符串的数据结构编写JSON Schema,示例数据如下:

{
  "supportedLanguages": ["en", "fr"],
  "serviceName": {
    "en": "My App",
    "fr": "Mon Application"
  },
  "customerSupportEmail": {
    "en": "help@myapp.com"
  }
}

我已经实现了按属性单独设置条件验证:当supportedLanguages包含某语言时,对应翻译字段必须包含该语言的键。现在希望通过$defs复用验证逻辑,于是尝试在if-then结构中修改$defs里的translatedString定义,代码如下:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "example",
  "type": "object",
  "properties": {
    "supportedLanguages": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": ["en", "fr", "de"]
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "serviceName": {
      "$ref": "#/$defs/translatedString"
    },
    "customerSupportEmail": {
      "$ref": "#/$defs/translatedString"
    }
  },
  "$defs": {
    "translatedString": {
      "type": "object",
      "properties": {
        "en": {
          "type": "string"
        },
        "fr": {
          "type": "string"
        },
        "de": {
          "type": "string"
        }
      }
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "supportedLanguages": {
            "type": "array",
            "contains": {
              "const": "en"
            }
          }
        }
      },
      "then": {
        "$defs": {
          "translatedString": {
            "type": "object",
            "required": ["en"]
          }
        }
      }
    }
  ]
}

但在Node.js的AJV中验证无效,请问是否存在方法在if-then-else结构中为$defs定义添加条件?


问题根源

你不能在if-then的then块中重新定义$defs——JSON Schema的$defs是静态的,只能在Schema的顶层(或嵌套的$defs块中)定义,无法通过条件逻辑动态修改引用的定义内容。AJV会忽略then块里的$defs,所以你的条件验证规则根本没生效。

正确实现方式

要复用验证逻辑,应该把条件验证逻辑直接整合到$defs的translatedString中,或者通过allOf结合动态规则来实现。这里推荐两种可行方案:

方案1:利用$data关键字动态关联(推荐)

通过AJV支持的$data关键字,可以直接根据supportedLanguages数组的值,动态要求翻译字段包含对应语言键:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "example",
  "type": "object",
  "properties": {
    "supportedLanguages": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": ["en", "fr", "de"]
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "serviceName": {
      "$ref": "#/$defs/translatedString"
    },
    "customerSupportEmail": {
      "$ref": "#/$defs/translatedString"
    }
  },
  "$defs": {
    "translatedString": {
      "type": "object",
      "properties": {
        "en": { "type": "string" },
        "fr": { "type": "string" },
        "de": { "type": "string" }
      },
      "required": {
        "$data": "/supportedLanguages"
      }
    }
  },
  "required": ["supportedLanguages"]
}

注意:使用此方案需要在初始化AJV时添加配置{ $data: true }来启用$data支持。

方案2:通过allOf批量添加条件规则

如果无法使用$data,可以为每个语言单独编写if-then规则,复用translatedString的基础定义:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "example",
  "type": "object",
  "properties": {
    "supportedLanguages": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": ["en", "fr", "de"]
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "serviceName": { "$ref": "#/$defs/translatedString" },
    "customerSupportEmail": { "$ref": "#/$defs/translatedString" }
  },
  "$defs": {
    "translatedString": {
      "type": "object",
      "properties": {
        "en": { "type": "string" },
        "fr": { "type": "string" },
        "de": { "type": "string" }
      }
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "supportedLanguages": { "contains": { "const": "en" } }
        }
      },
      "then": {
        "properties": {
          "serviceName": { "required": ["en"] },
          "customerSupportEmail": { "required": ["en"] }
        }
      }
    },
    {
      "if": {
        "properties": {
          "supportedLanguages": { "contains": { "const": "fr" } }
        }
      },
      "then": {
        "properties": {
          "serviceName": { "required": ["fr"] },
          "customerSupportEmail": { "required": ["fr"] }
        }
      }
    },
    {
      "if": {
        "properties": {
          "supportedLanguages": { "contains": { "const": "de" } }
        }
      },
      "then": {
        "properties": {
          "serviceName": { "required": ["de"] },
          "customerSupportEmail": { "required": ["de"] }
        }
      }
    }
  ],
  "required": ["supportedLanguages"]
}

这个方案兼容性更好,不需要依赖$data特性。

总结

  • 禁止在if-then块中修改$defs,这不符合JSON Schema规范。
  • 优先使用$data实现动态关联,代码更简洁高效。
  • 若无法使用$data,则通过allOf结合多个if-then规则复用验证逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:32:05