属性 的内容依赖于另一个 属性 值

Content of an property dependent on another property value

我有以下架构,"works",但不强制执行它所需的所有规则。

我收到 JSON 一系列具有 templateTypedata 属性的问题。每种类型都有不同的模板,类型必须符合模板(否则客户不知道如何布局数据)。

架构将 templateType 作为枚举进行验证,并且数据符合其中一个模板,但类型和数据结构之间没有关联(例如,我可以得到 templateType yesNo and data structure for multiSelect).

我希望它能验证 templateType 是否与数据结构匹配。我无法更改生成的 JSON 的格式,只能更改验证它的模式。 None 我看过的问题似乎提供了解决方案。

如需帮助,可以将架构粘贴到 http://jeremydorn.com/json-editor/ 处的编辑器中,它根据输入到表单中的选择和数据从架构和 JSON 数据生成表单。

{
  "definitions": {
    "question": {
      "type": "array",
      "title": "Question",
      "items": {
        "$ref": "#/definitions/template"
      }
    },
    "template": {
      "type": "object",
      "title": "Question template",
      "required": ["templateType","data"],
      "properties": {
        "templateType": {
          "type": "string",
          "enum": ["yesNo","multiSelect"]
        },
        "data": {
          "oneOf": [
            {"$ref": "#/definitions/yesNo"},
            {"$ref": "#/definitions/multiSelect"}
          ]
        }
      }
    },
    "yesNo": {
      "type": "object",
      "title": "Yes/No question",
      "additionalProperties": false,
      "properties": {
        "label": {
          "type": "string"
        }
      }
    },
    "multiSelect": {
      "type": "array",
      "title": "Multi-select question",
      "items": {
        "type": "string",
        "title": "Label for option",
        "additionalProperties": false
      }
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "items": {
    "$ref": "#/definitions/question"
  }
}

您是否考虑过在架构中使用 ifthenelse 关键字?他们是 JSON Schema draft-07

的一部分

看起来像这样:

{
  "definitions": {
    "question": {
      "type": "array",
      "title": "Question",
      "items": {
        "$ref": "#/definitions/template"
      }
    },
    "template": {
      "type": "object",
      "title": "Question template",
      "required": ["templateType","data"],
      "properties": {
        "templateType": {
          "type": "string",
          "enum": ["yesNo","multiSelect"]
        },
        "data": {
          "if": { "properties": { "templateType": { "pattern": "^yesNo$" } } },
          "then": { "$ref": "#/definitions/yesNo" },
          "else": { "$ref": "#/definitions/multiSelect" }
        }
      }
    },
    "yesNo": {
      "type": "object",
      "title": "Yes/No question",
      "additionalProperties": false,
      "properties": {
        "label": {
          "type": "string"
        }
      }
    },
    "multiSelect": {
      "type": "array",
      "title": "Multi-select question",
      "items": {
        "type": "string",
        "title": "Label for option",
        "additionalProperties": false
      }
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "items": {
    "$ref": "#/definitions/question"
  }
}

如果您的验证器不支持 if/then/else,替代方案可能是:

{
  "definitions": {
    "question": {
      "type": "array",
      "title": "Question",
      "items": {
        "$ref": "#/definitions/template"
      }
    },
    "template": {
      "type": "object",
      "title": "Question template",
      "required": ["templateType","data"],
      "anyOf": [
        {
          "properties": {
            "templateType": { "type": "string", "pattern": "yesNo" },
            "data": { "$ref": "#/definitions/yesNo" }
          }
        },
        {
          "properties": {
            "templateType": { "type": "string", "pattern": "multiSelect" },
            "data": { "$ref": "#/definitions/multiSelect" }
          }
        }
      ]
    },
    "yesNo": {
      "type": "object",
      "title": "Yes/No question",
      "additionalProperties": false,
      "properties": {
        "label": {
          "type": "string"
        }
      }
    },
    "multiSelect": {
      "type": "array",
      "title": "Multi-select question",
      "items": {
        "type": "string",
        "title": "Label for option",
        "additionalProperties": false
      }
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "items": {
    "$ref": "#/definitions/question"
  }
}