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

JSON Schema中oneOf与additionalProperties使用困惑及修正咨询

修正JSON Schema以禁止额外属性并保留鉴别器功能

问题根源

你的Schema允许额外属性,是因为Common、Type1和Type2都配置了additionalProperties: true,且通过allOf组合时,子Schema的宽松约束会覆盖主Schema的严格限制。直接全局设置additionalProperties: false失效,也是因为子Schema的true优先级导致约束冲突。

修正方案

调整Schema结构,将公共属性与类型专属属性合并,并在每个类型定义中明确禁止额外属性,同时保留type作为鉴别器的功能:

{
  "$id": "foo.schema.json",
  "oneOf": [
    { "$ref": "#/$defs/Type1" },
    { "$ref": "#/$defs/Type2" }
  ],
  "$defs": {
    "Common": {
      "type": "object",
      "properties": {
        "title": { "type": "string" }
      },
      "required": ["title"]
    },
    "Type1": {
      "allOf": [
        { "$ref": "#/$defs/Common" },
        {
          "type": "object",
          "properties": {
            "type": { "const": "type1" }
          },
          "required": ["type"]
        }
      ],
      "additionalProperties": false
    },
    "Type2": {
      "allOf": [
        { "$ref": "#/$defs/Common" },
        {
          "type": "object",
          "properties": {
            "type": { "const": "type2" }
          },
          "required": ["type"]
        }
      ],
      "additionalProperties": false
    }
  }
}

方案说明

  1. 类型鉴别:主Schema通过oneOf确保对象只能匹配Type1或Type2,自动拒绝type为type3的情况
  2. 公共属性约束:Common定义了必填的title字符串属性,所有类型都继承该约束
  3. 禁止额外属性:每个类型定义末尾设置additionalProperties: false,仅允许title和对应type属性(后续可扩展专属属性)
  4. 必填校验:Common和各类型分别约束title、type为必填,自动拒绝缺少type的对象

后续扩展专属属性

如果需要给Type1或Type2添加专属属性,只需在对应类型的properties中新增字段即可,例如给Type1添加detail属性:

"Type1": {
  "allOf": [
    { "$ref": "#/$defs/Common" },
    {
      "type": "object",
      "properties": {
        "type": { "const": "type1" },
        "detail": { "type": "string" } // 新增专属属性
      },
      "required": ["type"]
    }
  ],
  "additionalProperties": false
}

这样既保留了鉴别器功能,又严格控制了属性范围,完全满足你的校验需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:24:50