web-dev-qa-db-ja.com

JsonSchema:別のプロパティの値に基づいてタイプを検証します

次のスキーマを使用して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 ofを使用し、valueプロパティは配列ではないため、検証しないでください。

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

この方法で検証するために依存関係を設定することは可能ですか?

5
Joel Harris

これらの種類の問題を解決する最良の方法は、定義を使用して複雑な検証をスキーマの残りの部分から分離し、それを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" }
      }
    }
  }
}
6

JSONスキーマの最新のドラフト7バージョンを使用できる場合は、 https://tools.ietf.org/html/draft-handrews-json-schema)に従ってif then elseを使用できます。 -検証-00#section-6.6

oneOfを使用することも有効なアプローチですが、後日スキーマを検査する他の誰かにとってはそれほど明確ではない可能性があります。

別の質問 への回答から例をコピーしました:

「foo」プロパティが「bar」と等しい場合、「bar」プロパティが必要です

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

(使用しているライブラリのドラフトサポートを確認することをお勧めします。)

2
Relequestual

これを行うにはもっと簡潔な方法があるかもしれませんが、これはうまくいきます:

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