title: Conditional JSON schema based on dynamic property value
body: <p>I'm trying to validate a JSON file that contains several nested components of the same type. Each component has a <code>class</code> string property. I'm trying to apply different validation schemas from my definitions to each component based on the value of <code>class</code>. Furthermore, the values of <em>class</em> can be "button-open", "button-close", "icon-message", "icon-...", "container", etc and I would like to apply the same validation schema for all the "buttons-" another to "icons-" and another to the rest.</p>
  
  <p>The code I provide is what I have tried. I have excluded <code>icons-</code> for the shake of simplicity. As you can see I tried to match with a regular expression whenever there is <code>button</code> in <code>class</code>. Then it should constraint the minimum value of children elements to 1. </p>
  
  <pre><code>{
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "required": ["results"],
      "properties": {
          "results": {
              "type": "array",
              "minItems": 1,
              "items": {
                  "type": "object",
                  "anyOf": [
                      {
                          "$ref": "#/definitions/genericComponent"
                      },
                      {
                          "$ref": "#/definitions/button"
                      }
                  ]
              }
          }
      },
      "definitions": {
          "genericComponent": {
              "type": "object",
              "$id": "#/definitions/genericComponent",
              "required":[
                  "class",
                  "children"
              ],
              "properties":{
                  "class": {
                      "type": "string",
                      "description": "predicted class of the element(img, icon..)"
                  },
                  "children":{
                      "type": "array",
                      "description": "this element can contain more of the same type",
                      "items":{
                          "type": "object",
                          "anyOf":[
                              {"$ref": "#/definitions/button"},
                              {"$ref": "#/definitions/genericComponent"}
                          ]
                      }
                  }
              }
          },
          "button": {
              "$id": "#/definitions/button",
              "allOf":[
                  {"$ref": "#/definitions/genericComponent"},
                  {"properties": {
                      "class":{
                          "type":"string",
                          "pattern": "(button)"
                      },
                      "children":{
                          "type": "array",
                          "description": "this element must contain one generic element",
                          "items":{
                              "type": "object",
                              "$ref": "#/definitions/genericComponent"
                          },
                          "minItems": 1,
                          "maxItems": 1
                      }
                  }}
              ]
          }
      }
  }
  </code></pre>
  
  <p>I also tried to apply the property conditionally as: </p>
  
  <pre><code>{
      "type": "object",
      "required": ["results"],
      "properties": {
          "results": {
              "type": "array",
              "minItems": 1,
              "items": {
                  "type": "object",
                  "$ref": "#/definitions/genericComponent"
              }
          }
      },
      "definitions": {
          "genericComponent": {
              "type": "object",
              "$id": "#/definitions/genericComponent",
              "required":[
                  "class",
                  "children"
              ],
              "properties":{
                  "class":{
                      "type": "string"
                  },
                  "children":{
                      "type": "array",
                      "items": {
                          "type": "object",
                          "anyOf":[
                              {"$ref":"#/definitions/genericComponent"},
                              {"$ref":"#/definitions/button"}
                          ]
                      }
                  }
              },  
              "if": {
                  "properties": {"class": {"pattern": "^button-rect$"}}
              },
              "then": {
                  "properties": {
                      "children":{
                          "type": "array",
                          "items": {
                              "type": "object",
                              "$ref": "#/definitions/genericComponent"
                           },
                           "minItems": 1,
                      }
                  }
              },
              "else": {
                  "properties": {
                      "children":{
                          "type": "array",
                          "items": {
                              "type": "object",
                              "$ref": "#/definitions/genericComponent"
                          }
                      }
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>EDIT: this one sample that pass but it shouldn't as the number of children of one of the buttons is highier of 1.</p>
  
  <pre><code>{"results": [
    {
      "class": "box",
      "children": [
        {
          "class": "icon",
          "children": []
        },
        {
          "class": "button-rect",
          "children": [
            {
              "class": "label",
              "children": []
            }
          ]
        },
        {
          "class": "button-round",
          "children": [
            {
              "class": "label",
              "children": []
            },
            {
              "class": "label",
              "children": []
            }
          ]
        }
      ]
    }
  ]
  }
  </code></pre>