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

如何用JSON Schema实现查询仅允许另一Schema定义的键并支持多值匹配?

实现复用枚举键+支持多值查询的JSON Schema方案

这是个很常见的JSON Schema复用需求,我来给你拆解实现步骤,既避免代码重复,又满足查询时的多值匹配要求:

第一步:构建可复用的options.json

我们先把带枚举值的键定义在这个Schema里,并且把枚举值抽离到可复用的块中,方便后续query schema引用:

// options.json (基于Draft 07,兼容性更广)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  // 抽离枚举定义到definitions,方便后续复用
  "definitions": {
    "colorEnum": {
      "type": "string",
      "enum": ["red", "green", "blue"]
    },
    "sizeEnum": {
      "type": "string",
      "enum": ["small", "medium", "large"]
    }
  },
  "type": "object",
  "properties": {
    "color": {"$ref": "#/definitions/colorEnum"},
    "size": {"$ref": "#/definitions/sizeEnum"}
  },
  // 禁止额外未定义的键
  "additionalProperties": false
}

第二步:构建query.json实现键复用+多值支持

接下来,我们要让query schema仅允许使用options.json里的键,同时每个键的值可以是单个枚举值或者多个枚举值的数组(满足多值匹配需求):

// query.json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  // 复用options里定义的所有键,但重写每个键的验证规则
  "properties": {
    "color": {
      "anyOf": [
        // 允许单个枚举值(直接引用options里的定义)
        {"$ref": "options.json#/definitions/colorEnum"},
        // 允许枚举值的数组,且数组元素不重复、至少有一个值
        {
          "type": "array",
          "items": {"$ref": "options.json#/definitions/colorEnum"},
          "uniqueItems": true,
          "minItems": 1
        }
      ]
    },
    "size": {
      "anyOf": [
        {"$ref": "options.json#/definitions/sizeEnum"},
        {
          "type": "array",
          "items": {"$ref": "options.json#/definitions/sizeEnum"},
          "uniqueItems": true,
          "minItems": 1
        }
      ]
    }
  },
  // 严格禁止使用options里未定义的键
  "additionalProperties": false,
  // 可选:要求至少传一个查询参数
  "minProperties": 1
}

核心逻辑解释

  • 复用枚举定义:通过$ref直接引用options.json里的枚举,避免重复编写枚举值,后续修改枚举只需要改options.json即可。
  • 多值支持:用anyOf让每个键的值可以是单个枚举值,或者由枚举值组成的数组;uniqueItems: true防止数组里出现重复值(可根据需求移除)。
  • 键合法性限制:additionalProperties: false确保查询请求只能使用options.json里定义的键,杜绝非法参数。

验证示例

合法的查询请求

{
  "color": ["red", "green"],
  "size": "medium"
}

非法的查询请求

  1. 使用未定义的键:
{
  "shape": "circle" // shape不在options的键列表中,验证失败
}
  1. 使用不在枚举中的值:
{
  "color": "yellow" // yellow不在colorEnum的枚举里,验证失败
}
  1. 数组包含重复值:
{
  "color": ["red", "red"] // uniqueItems限制重复,验证失败
}

进阶优化(Draft 2020-12版本)

如果你的JSON Schema支持Draft 2020-12,可以用$dynamicRef更优雅地复用整个键结构,不需要手动复制properties:

// options.json (Draft 2020-12)
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$anchor": "optionsSchema",
  "$defs": {
    "colorEnum": {"type": "string", "enum": ["red", "green", "blue"]},
    "sizeEnum": {"type": "string", "enum": ["small", "medium", "large"]}
  },
  "type": "object",
  "properties": {
    "color": {"$ref": "#/$defs/colorEnum"},
    "size": {"$ref": "#/$defs/sizeEnum"}
  },
  "additionalProperties": false
}
// query.json (Draft 2020-12)
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  // 动态复用options的键结构
  "$dynamicRef": "options.json#optionsSchema",
  "$dynamicAnchor": "optionsSchema",
  // 重写每个键的验证规则以支持多值
  "properties": {
    "color": {
      "anyOf": [
        {"$ref": "options.json#/$defs/colorEnum"},
        {"type": "array", "items": {"$ref": "options.json#/$defs/colorEnum"}, "uniqueItems": true}
      ]
    },
    "size": {
      "anyOf": [
        {"$ref": "options.json#/$defs/sizeEnum"},
        {"type": "array", "items": {"$ref": "options.json#/$defs/sizeEnum"}, "uniqueItems": true}
      ]
    }
  },
  "additionalProperties": false
}

这种方式更适合键较多的场景,不需要手动维护query schema里的properties列表,直接复用options的键结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:27:08