JsonSchema: Validate type based on value of another property

自古美人都是妖i 提交于 2019-12-01 06:50:29

The best way to solve these kinds of problems is to separate the complex validation from the rest of the schema using definitions and include it with an allOf. In this solution, I use implication to enforce the validation.

{
  "type": "object",
  "properties": {
    "rules": {
      "type": "array",
      "items": { "$ref": "#/definitions/rule" }
    }
  },
  "required": ["rules"],
  "definitions": {
    "rule": {
      "type": "object",
      "properties": {
        "precedence": { "type": "number", "minimum": 0 },
        "conditions": {
          "type": "array",
          "items": { "$ref": "#/definitions/condition" }
        }
      },
      "required": ["precedence", "conditions"]
    },
    "condition": {
      "type": "object",
      "properties": {
        "field": { "enum": ["Name", "Size"] },
        "relation": { "enum": ["is", "is not", "is not one of", "is one of"] },
        "value": { "type": ["array", "string", "number"] }
      },
      "required": ["field", "relation", "value"],
      "allOf": [{ "$ref": "#/definitions/array-condition-implies-value-is-array" }]
    },
    "array-condition-implies-value-is-array": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/is-array-condition" } },
        { "$ref": "#/definitions/value-is-array" }
      ]
    }
    "is-array-condition": {
      "properties": {
        "relation": { "enum": ["is not one of", "is one of"] }
      },
      "required": ["relation"]
    },
    "value-is-array": {
      "properties": {
        "value": { "type": "array" }
      }
    }
  }
}

If you are able to use the latest draft-7 version of JSON Schema, you can use if then else, as per https://tools.ietf.org/html/draft-handrews-json-schema-validation-00#section-6.6

Although, using oneOf is also a valid approach, it might not be as clear to someone else inspecting your schema at a later date.

I've copied an example from an answer to another question:

If the "foo" property equals "bar", Then the "bar" property is required

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "if": {
    "properties": {
      "foo": { "enum": ["bar"] }
    }
  },
  "then": { "required": ["bar"] }
}

(You may want to check the draft support of the library you are using.)

There may be a more concise way to do this, but this will work:

{
  "$schema": "http://json-schema.org/schema#",
  "title": "Rules",
  "description": "Describes a set of rules",
  "definitions": {
    "field": {
      "type": "string",
      "enum": ["Name", "Size"]
    }
  },
  "type": "object",
  "properties": {
    "rules": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "precedence": {
            "type": "number",
            "minimum": 0
          },
          "conditions": {
            "type": "array",
            "items": {
              "type": "object",
              "oneOf": [
                {
                  "properties": {
                    "field": {
                      "$ref": "#/definitions/field"
                    },
                    "relation": {
                      "type": "string",
                      "enum": ["is", "is not"]
                    },
                    "value": {
                      "type": ["string", "number"]
                    }
                  },
                  "required": ["field", "relation", "value"],
                  "additionalProperties": false
                },
                {
                  "properties": {
                    "field": {
                      "$ref": "#/definitions/field"
                    },
                    "relation": {
                      "type": "string",
                      "enum": ["is not one of", "is one of"]
                    },
                    "value": {
                      "type": ["array"]
                    }
                  },
                  "required": ["field", "relation", "value"],
                  "additionalProperties": false
                }
              ]
            }
          }
        },
        "required": ["precedence", "conditions"],
        "additionalProperties": false
      }
    }
  },
  "required": ["rules"],
  "additionalProperties": false
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!