Search code examples
jsonschemaajv

JSON Schema not working as expected, this seems to be common issue when the property is boolean type


The following JSON Schema seems to be failing and I'm not sure why this is happening. I tried adding not required instead of else, but it had no effect. I've tried several things, but nothing seems to work. I want to make only one field strictly available and else based on some other boolean.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Update app config Support & Ticketing",
      "type": "object",
        "properties": {
    "servicenowEnabled": {
      "type": "boolean"
    },
    "servicenowClientId": {
      "type": "string"
    },
    "servicenowClientSecret": {
      "type": "string"
    },
    "servicenowBaseUrl": {
      "type": "string",
        "format": "regex",
          "pattern": ".*service-now.com$"
    },
    "servicenowKnowledgeBaseEnabled": {
      "type": "boolean"
    },
    "servicenowKnowledgeBaseSelected": {
      "type": "object",
        "properties": {
        "showAll": {
          "type": "boolean"
        },
        "selectedList": {
          "type": "array",
            "items": {
            "type": "object"
          },
          "properties": {
            "id": {
              "type": "string",
                "minLength": 1
            },
            "name": {
              "type": "string",
                "minLength": 1
            }
          }
        }
      },
      "required": [
        "showAll"
      ],
        "if": {
        "properties": {
          "showAll": {
            "const": true
          }
        }
      },
      "then": {
        "properties": {
          "selectedList": {
            "const": []
          }
        }
      },
      "else": {
        "properties": {
          "selectedList": {
            "minItems": 1
          }
        }
      }
    },
    "servicenowKnowledgeBaseName": {
      "type": "string",
        "minLength": 1
    },
    "servicenowKnowledgeBaseUrl": {
      "type": "string",
        "format": "uri"
    },
    "servicenowTicketsEnabled": {
      "type": "boolean"
    },
    "servicenowTicketsName": {
      "type": "string",
        "minLength": 1
    },
    "servicenowTicketsUrl": {
      "type": "string",
        "format": "uri"
    },
    "servicenowCreateTicketsEnabled": {
      "type": "boolean"
    },
    "servicenowNotificationEnabled": {
      "type": "boolean"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "servicenowEnabled": {
            "const": true
          }
        }
      },
      "then": {
        "required": [
          "servicenowEnabled",
          "servicenowBaseUrl"
        ]
      },
      "else": {
        "required": [
          "servicenowEnabled"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "servicenowKnowledgeBaseEnabled": {
            "const": true
          }
        }
      },
      "then": {
        "required": [
          "servicenowKnowledgeBaseUrl",
          "servicenowKnowledgeBaseName",
          "servicenowKnowledgeBaseSelected"
        ]
      },
      "else": true
    }
  ],
    "additionalProperties": false
}

fails for the test case of

{
  "servicenowEnabled": false,
  "servicenowBaseUrl": "http: //base-url.service-now.com",
  "servicenowClientId": "clientID",
  "servicenowClientSecret": "clientSecret"
}

Solution

  • You had an error in the schema on line 34, properties was not defined correctly.

    I fixed up the if, then statements for you. Now, the example you provided is passing.

    • servicenowEnabled must be required in the if part of the conditional schema.
    • if the value is true, servicenowBaseUrl is required

    the same is true for the second allOf conditional statement

    • servicenowKnowledgeBaseEnabled must be required for it to validate correctly.

    Note The “required” keyword is necessary in the if schemas or all properties would apply if no properties were defined or required at the root schema where the if, then conditions are present

    I also added a few more constraints on selectedList required properties and the requirement of selectedList itself when the showAll: false condition is met.

    Please check and let me know if that works for you.

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Update app config Support & Ticketing",
      "type": "object",
      "properties": {
        "servicenowEnabled": {
          "type": "boolean"
        },
        "servicenowClientId": {
          "type": "string"
        },
        "servicenowClientSecret": {
          "type": "string"
        },
        "servicenowBaseUrl": {
          "type": "string",
          "format": "regex",
          "pattern": ".*service-now.com$"
        },
        "servicenowKnowledgeBaseEnabled": {
          "type": "boolean"
        },
        "servicenowKnowledgeBaseSelected": {
          "type": "object",
          "properties": {
            "showAll": {
              "type": "boolean"
            },
            "selectedList": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["id", "name"],
                "properties": {
                  "id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1
                  }
                }
              }
            }
          },
          "required": ["showAll"],
          "if": {
            "properties": {
              "showAll": {
                "const": false
              }
            }
          },
          "then": {
            "required": ["selectedList"],
            "properties": {
              "selectedList": {
                "minItems": 1
              }
            }
          }
        },
        "servicenowKnowledgeBaseName": {
          "type": "string",
          "minLength": 1
        },
        "servicenowKnowledgeBaseUrl": {
          "type": "string",
          "format": "uri"
        },
        "servicenowTicketsEnabled": {
          "type": "boolean"
        },
        "servicenowTicketsName": {
          "type": "string",
          "minLength": 1
        },
        "servicenowTicketsUrl": {
          "type": "string",
          "format": "uri"
        },
        "servicenowCreateTicketsEnabled": {
          "type": "boolean"
        },
        "servicenowNotificationEnabled": {
          "type": "boolean"
        }
      },
      "allOf": [
        {
          "if": {
            "required": ["servicenowEnabled"],
            "properties": {
              "servicenowEnabled": {
                "const": true
              }
            }
          },
          "then": {
            "required": ["servicenowBaseUrl"]
          }
        },
        {
          "if": {
            "required": ["servicenowKnowledgeBaseEnabled"],
            "properties": {
              "servicenowKnowledgeBaseEnabled": {
                "const": true
              }
            }
          },
          "then": {
            "required": [
              "servicenowKnowledgeBaseUrl",
              "servicenowKnowledgeBaseName",
              "servicenowKnowledgeBaseSelected"
            ]
          }
        }
      ],
      "additionalProperties": false
    }