Stefan
Stefan

Reputation: 1284

How to validate data based on an input value with AJV?

I am using AJV trying to validate some data and dynamically require properties based on another property's value.

What I am trying to validate is: - enabled is always required, - if enabled = true then only one of the other properties (realtime, threshold or digest) must be provided,

Sample payloads and expected results:

Should pass

{
  "notifications": {
    "enabled": false
  }
}

Should pass

{
  "notifications": {
    "enabled": true,
    "realtime": true
  }
}

Should pass

{
  "notifications": {
    "enabled": true,
    "digest": true
  }
}

Should pass

{
  "notifications": {
    "enabled": true,
    "threshold": {}
  }
}

Should fail because enabled = true but no other property is set.

{
  "notifications": {
    "enabled": true
  }
}

Should fail because enabled = true and more than one other property is set.

{
  "notifications": {
    "enabled": true,
    "threshold": {},
    "digest: true
  }
}

Here's the validation schema I am using:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Settings",
  "type": "object",
  "properties": {
    "notifications": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean"
        },
        "realtime": {
          "type": "boolean"
        },
        "threshold": {
          "type": "object",
          "properties": {
            "detections": {
              "type": "number"
            },
            "elapsed": {
              "type": "number"
            }
          },
          "required": ["detections", "elapsed"]
        },
        "digest": {
          "type": "boolean"
        }
      },
      "required": ["enabled"],
      "if": {
        "properties": { "enabled": true }
      },
      "then": {
        "oneOf": [
          { "required": [ "realtime" ] },
          { "required": [ "threshold" ] },
          { "required": [ "digest" ] }
        ]
      }
    }
  }
}

Thank you!

Upvotes: 3

Views: 3104

Answers (1)

Stefan
Stefan

Reputation: 1284

Turns out I was very close and the problem was how the if statement was being evaluated for true. Here's the correct schema that validates (passes and fails) all examples above as expected:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Settings",
  "type": "object",
  "properties": {
    "notifications": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean"
        },
        "realtime": {
          "type": "boolean"
        },
        "threshold": {
          "type": "object",
          "properties": {
            "detections": {
              "type": "number"
            },
            "elapsed": {
              "type": "number"
            }
          },
          "required": ["detections", "elapsed"]
        },
        "digest": {
          "type": "boolean"
        }
      },
      "required": ["enabled"],
      "if": {
        "enabled": {
          "const": true
        }
      },
      "then": {
        "oneOf": [
          {
            "required": ["realtime"]
          },
          {
            "required": ["threshold"]
          },
          {
            "required": ["digest"]
          }
        ]
      }
    }
  }
}

This part did the trick:

"if": {
    "properties": {
        "enabled": {
            "const": true
        }
    }
}

Upvotes: 4

Related Questions