Ilya Lepesh
Ilya Lepesh

Reputation: 103

JSON Schema: Dependency across array elements

What is the right way to require an array element with particular field if other array element is presented?
E.g. forcing bread in case if butter is here:

+-------+-------+--------+
| valid | bread | butter |
+-------+-------+--------+
|   +   |   -   |   -    |
|   +   |   +   |   -    |
|   +   |   +   |   +    |
|   -   |   -   |   +    |
+-------+-------+--------+

Products example:

{
  "products": [
    {
      "name": "butter"
    },
    {
      "name": "bread"
    }
  ]
}

Based on post and Combining schemas, it is possible to check that there is NO butter, otherwise array has bread:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Complex Array",

  "anyOf": [
    { "not": { "$ref": "#/definitions/contains-name-butter" } },
    { "$ref": "#/definitions/contains-name-bread" }
  ],
  "definitions": {
    "contains-name-butter": {
      "type": "object",
      "properties": {
        "products": {
          "type": "array",
          "contains": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "pattern": "^butter$"
              }
            }
          }
        }
      }
    },
    "contains-name-bread": {
      "type": "object",
      "properties": {
        "products": {
          "type": "array",
          "contains": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "pattern": "^bread$"
              }
            }
          }
        }
      }
    }
  }
}

Now if bread got removed - schema validation will break.

If there any way to make it simpler? Especially if in future adding more dependency is planned.

Upvotes: 0

Views: 738

Answers (1)

Ether
Ether

Reputation: 53966

In logical terms, what you seem to want is: if the array contains an item with property "name" whose value is "butter", then require an item with property "name" and value "bread":

  "type" : "array",
  "if" : {
    "contains" : {
      "type: "object",
      "properties" : {
        "name" : {
          "const" : "butter"
        }
      }
    }
  },
  "then" : {
    "contains" : {
      "required": [ "name" ],
      "properties" : {
        "name" : {
          "const" : "bread"
        }
      }
    }
  }
}

(I also, simplified "pattern": "^bread$" as "const":"bread".)

Upvotes: 2

Related Questions