一个属性的内容取决于另一个属性值

时间:2018-11-28 07:49:42

标签: jsonschema

我具有以下模式,该模式“有效”,但并未强制执行所有必需的规则。

我得到带有一系列具有 templateType data 属性的问题的JSON。每种类型都有不同的模板,并且类型必须适合该模板(否则客户端不知道如何布局数据)。

该模式将 templateType 验证为枚举,并且数据适合其中一个模板,但是类型和数据结构之间没有关联(例如,我可以获取 templateType yesNo和multiSelect的数据结构。

我希望它验证 templateType 是否与数据结构匹配。我无法更改生成的JSON的格式,只能更改可对其进行验证的架构。我看过的所有问题似乎都没有提供解决方案。

要获取帮助,可以将模式粘贴到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"
  }
}

1 个答案:

答案 0 :(得分:1)

您是否考虑过在架构中使用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"
  }
}