Gerson Goulart
Gerson Goulart

Reputation: 634

Validate JSON Schema properties with at least one containing specific value

I would like to know if I can define a JSON schema (draft 4) that requires at least one of many properties to have a specific value.

To illustrate, here is an example JSON I expect to FAIL the validation:

{
    "daysOfWeek": {
        "mon": false,
        "tue": false,
        "wed": false,
        "thu": false,
        "fri": false,
        "sat": false,
        "sun": false
    }
}

But if any (one or more) of the above properties is set to true, only then I'd expect it to PASS the validation.

So what would the Schema be?

{
    "daysOfWeek": {
        "type": "object",
        "properties": {
            "mon": { "type": "boolean" },
            "tue": { "type": "boolean" },
            "wed": { "type": "boolean" },
            "thu": { "type": "boolean" },
            "fri": { "type": "boolean" },
            "sat": { "type": "boolean" },
            "sun": { "type": "boolean" }
        },
        "anyOf": [{
            // ?
        }]
    }
}

Many thanks in advance!

Upvotes: 1

Views: 1184

Answers (2)

cloudfeet
cloudfeet

Reputation: 12891

@Jason's answer is good (and readable) for the case you have here. In the general case (where you might have arbitrary numbers of properties), there's a more concise way (but less readable):

You could rephrase your requirement as "The properties are not all allowed to be false", in which case a schema could be:

{
    "type": "object",
    "properties": {...},
    "not": {
        "additionalProperties": {"enum": [false]}
    }
}

The additionalProperties is in a sub-schema, so it's not connected to the properties value at the root level. It therefore applies to all the properties.

The subschema inside not will only pass if all properties are false - therefore the outer schema will only pass if not all the properties are false.

Upvotes: 3

Jason Desrosiers
Jason Desrosiers

Reputation: 24489

You can use the enum keyword to specify that a property has a specific value. You can combine that trick with anyOf to get the desired validation behavior.

{
  "type": "object",
  "properties": {
    "daysOfWeek": {
      "type": "object",
      "properties": {
        "mon": { "type": "boolean" },
        "tue": { "type": "boolean" },
        "wed": { "type": "boolean" },
        "thu": { "type": "boolean" },
        "fri": { "type": "boolean" },
        "sat": { "type": "boolean" },
        "sun": { "type": "boolean" }
      },
      "anyOf": [
        {
          "properties": {
            "mon": { "enum": [true] }
          }
        },
        {
          "properties": {
            "tue": { "enum": [true] }
          }
        },
        {
          "properties": {
            "wed": { "enum": [true] }
          }
        },
        {
          "properties": {
            "thu": { "enum": [true] }
          }
        },
        {
          "properties": {
            "fri": { "enum": [true] }
          }
        },
        {
          "properties": {
            "sat": { "enum": [true] }
          }
        },
        {
          "properties": {
            "sun": { "enum": [true] }
          }
        }
      ]
    }
  }
}

Upvotes: 1

Related Questions