JSON 架构:验证自定义 $ref'd 对象数组

JSON Schema: validating an array of custom $ref'd objects

背景:嗨!我一直在尝试使用一种模式来验证对象内的数组是否包含 我的 definitions 块内定义的一些对象。

例如,我要验证以下 JSON 数据:

{
   "component_type":"section",
   "component_properties":{
      "section_name":"first_section",
      "fields":[
         {
            "component_type":"spacer",
            "component_properties":{
               "width":6
            }
         },
         {
            "component_type":"textbox",
            "component_properties":{
               "display_text":"hello!",
               "text_color":"black"
            }
         },
         {
            "component_type":"spacer",
            "component_properties":{
               "width":3
            }
         }
      ]
   }
}

此数据背后的想法是,在最高级别定义了一个 section "component",填充了定义为要验证的子组件(spacer , textbox).

我的主要问题: 我不太明白如何验证仅由几个定义的对象组成的数组。我当前的架构如下:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "properties": {
    "component_type": {
      "type": "string",
      "const": "section"
    },
    "component_properties": {
      "type": "object",
      "properties": {
        "section_name": { "type": "string"},
        "sections": {
          "type": "array",
          "oneOf": [
            { "$ref": "#/definitions/section_field" },
            { 
              "type": "array",
              "items": {
                "$ref": "#/definitions/section_field"
              }
            }
          ]
        }
      }
    }
  },
  "definitions": {
    "spacer": {
      "type": "object",
      "properties": {
        "component_type": {
          "type": "string",
          "const": "spacer"
        },
        "component_properties": {
          "width": "number"
        }
      }
    },
    "textbox": {
      "type": "object",
      "properties": {
        "component_type": {
          "type": "string",
          "const": "textbox"
        },
        "component_properties": {
          "display_text": "hello!",
          "text_color": "purple"
        }
      }
    },
    "section_field": {
      "oneOf": [
        {
          "$ref": "#/definitions/spacer"
        },
        {
          "$ref": "#/definitions/textbox"
        }
      ]
    }
  }
}

此架构无法确保 component_properties 的 "fields" 数组内的所有项目在节级别都具有字段 "component_type": "spacer""component_type": "textbox"。例如,"component_type": "another_one" 应该无法通过验证。

如果有任何其他信息对您有帮助,请随时告诉我!如果能提供一些指导,我将不胜感激。

你的架构几乎没问题——除了以下细节:

  1. sections属性里面的”type”: “array”应该去掉。只有 ”oneOf” 应该保留。否则第一个 "oneOf" 部分(单个元素)将永远无效。
  2. "component_properties" 应该属于 "type": "object" 本身,然后在其 "properties" 中列出 width/display_text/text_color。看起来,您只是复制了示例内容。

但是,由于拼写错误,您的架构接受了您的示例:

  • 在您的示例中,您有一个 fields 属性。但在您的架构中,它被称为 sections。我假设它应该在两者中都被称为 fields

由于 none 个属性被标记为 required,因此给定的示例可以正常验证。 fields 属性 没有限制。 如果您将 sections 标记为 required,它会抱怨。


总而言之,您的架构的以下版本应该可以满足您的要求:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "required": ["component_type", "component_properties"],
  "properties": {
    "component_type": { "const": "section" },
    "component_properties": {
      "type": "object",
      "required": ["section_name", "fields"],
      "properties": {
        "section_name": { "type": "string" },
        "fields": {
          "oneOf": [
            { "$ref": "#/definitions/section_field" },
            { 
              "type": "array",
              "items": { "$ref": "#/definitions/section_field" }
            }
          ]
        }
      }
    }
  },
  "definitions": {
    "spacer": {
      "type": "object",
      "required": ["component_type", "component_properties"],
      "properties": {
        "component_type": { "const": "spacer" },
        "component_properties": {
          "properties": {
            "width": { "type": "number" }
          }
        }
      }
    },
    "textbox": {
      "type": "object",
      "required": ["component_type", "component_properties"],
      "properties": {
        "component_type": { "const": "textbox" },
        "component_properties": {
          "type": "object",
          "properties": {
            "display_text": { "type": "string" },
            "text_color": { "type": "string" }
          }
        }
      }
    },
    "section_field": {
      "oneOf": [
        { "$ref": "#/definitions/spacer" },
        { "$ref": "#/definitions/textbox" }
      ]
    }
  }
}