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

如何用anyOf定义两组patternProperties并禁用额外属性?

问题

尝试使用anyOf定义两组patternProperties,期望排除所有不符合任一模式的属性,但在为这两组patternProperties设置additionalProperties: false后,出现了属性无匹配的错误。

示例JSON数据:

{
  "fruitbasket": {
    "apple": {
      "color": "green"
    },
    "pear": {
      "color": "green"
    },
    "banana": {
      "color": "yellow"
    },
    "apple_wrapper": {
      "material": "paper"
    },
    "pear_wrapper": {
      "material": "cloth"
    },
    "banana_wrapper": {
      "material": "none"
    }
  }
}

使用的Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/responseobject",
  "definitions": {
    "responseobject": {
      "type": "object",
      "properties": {
        "fruitbasket": {
          "anyOf": [
            {
              "$ref": "#/definitions/fruit"
            },
            {
              "$ref": "#/definitions/wrapper"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "fruit": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)$": {
          "type": "object",
          "properties": {
            "color": {
              "type": "string",
              "enum": [
                "green",
                "yellow",
                "red"
              ]
            }
          },
          "required": [
            "color"
          ],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    },
    "wrapper": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)_wrapper$": {
          "properties": {
            "material": {
              "type": "string",
              "enum": [
                "paper",
                "cloth",
                "none"
              ]
            }
          },
          "required": [
            "material"
          ],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }
  }
}

当前现象:移除任意一组patternProperties旁的"additionalProperties": false,Schema即可通过验证。请问JSON Schema是否支持这种严格性?该如何实现仅允许两组patternProperties且无其他属性?

解答

问题原因

anyOf的逻辑是实例只需满足其中一个子Schema即可。你的fruit Schema要求所有属性都匹配^(apple|pear|banana)$模式,wrapper Schema要求所有属性都匹配^(apple|pear|banana)_wrapper$模式,但你的JSON实例同时包含两类属性,所以单独用fruit或wrapper验证时,另一类属性会被各自的additionalProperties: false判定为非法的额外属性,导致anyOf的两个分支都验证失败。

解决方案

JSON Schema完全支持这种严格校验需求,最直接的实现方式是合并两组patternProperties到同一个对象Schema中,然后设置additionalProperties: false,这样就能同时允许两类合法属性,且拒绝任何不符合模式的属性:

修改后的Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/responseobject",
  "definitions": {
    "responseobject": {
      "type": "object",
      "properties": {
        "fruitbasket": {
          "$ref": "#/definitions/fruitAndWrapper"
        }
      },
      "additionalProperties": false
    },
    "fruitAndWrapper": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)$": {
          "type": "object",
          "properties": {
            "color": {
              "type": "string",
              "enum": ["green", "yellow", "red"]
            }
          },
          "required": ["color"],
          "additionalProperties": false
        },
        "^(apple|pear|banana)_wrapper$": {
          "type": "object",
          "properties": {
            "material": {
              "type": "string",
              "enum": ["paper", "cloth", "none"]
            }
          },
          "required": ["material"],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }
  }
}

备选方案(若需保留anyOf结构)

如果后续有扩展多组规则的需求,必须使用anyOf,可以调整为:不在anyOf的子分支中设置additionalProperties: false,而是在外部通过not规则排除所有不匹配任一模式的属性:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/responseobject",
  "definitions": {
    "responseobject": {
      "type": "object",
      "properties": {
        "fruitbasket": {
          "allOf": [
            {
              "anyOf": [
                { "$ref": "#/definitions/fruit" },
                { "$ref": "#/definitions/wrapper" }
              ]
            },
            {
              "not": {
                "patternProperties": {
                  "^(?!(apple|pear|banana)(_wrapper)?$).*$": { "type": "object" }
                }
              }
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "fruit": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)$": {
          "type": "object",
          "properties": {
            "color": { "type": "string", "enum": ["green", "yellow", "red"] }
          },
          "required": ["color"],
          "additionalProperties": false
        }
      }
    },
    "wrapper": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)_wrapper$": {
          "type": "object",
          "properties": {
            "material": { "type": "string", "enum": ["paper", "cloth", "none"] }
          },
          "required": ["material"],
          "additionalProperties": false
        }
      }
    }
  }
}

这种方式通过allOf组合anyOf(允许匹配任意一类属性)和not(禁止匹配不到任一模式的属性),达到同样的严格校验效果,但复杂度更高,仅推荐在有特殊扩展需求时使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:24:53