JsonSchema:根据另一个 属性 的值验证类型

JsonSchema: Validate type based on value of another property

我正在使用以下架构来验证我的 json:

{
    "$schema": "http://json-schema.org/schema#",
    "title": " Rules",
    "description": "Describes a set of rules",
    "type": "object",
    "properties": {
        "rules": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "precedence": {
                        "type": "number",
                        "minimum": 0
                    },
                    "conditions": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "field": {
                                    "type": "string",
                                    "enum": [ "Name", "Size" ]
                                },
                                "relation": {
                                    "type": "string",
                                    "enum": [ "is", "is not", "is not one of", "is one of" ]
                                },
                                "value": {
                                    "type": ["array", "string", "number"]
                                }
                            },
                            "required": ["field", "relation", "value"],
                            "additionalProperties": false
                        }
                    }                       
                },
                "required": ["precedence", "conditions"],
                "additionalProperties": false
            }
        }
    },
    "required": ["rules"],
    "additionalProperties": false
}

我想建立一个依赖来验证当 relation 属性 的值具有值 is one of 或值 is not one of 时,则类型的 value 属性 只能是 array

例如,下面的 json 不应验证,因为它使用关系值 is not one ofvalue 属性 不是数组:

{
    "rules": [{
            "precedence": 0,
            "conditions": [{
                    "field": "Name",
                    "relation": "is not one of",
                    "value": "Mary"
                }
            ]
        }
    ]
}

是否可以设置依赖项以这种方式进行验证?

可能有更简洁的方法来执行此操作,但这会起作用:

{
  "$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
}

解决此类问题的最佳方法是使用定义将复杂验证与架构的其余部分分开,并将其包含在 allOf 中。在此解决方案中,我使用暗示来强制执行验证。

{
  "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" }
      }
    }
  }
}

如果您能够使用最新的 draft-7 版本的 JSON 架构,您可以使用 if then else,根据 https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-00#section-6.6

尽管使用 oneOf 也是一种有效的方法,但以后检查您的架构的其他人可能不太清楚。

我从 的回答中复制了一个示例:

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"] }
}

(您可能需要检查您正在使用的库的草稿支持。)