beatcracker
beatcracker

Reputation: 6920

Ajv doesn't validate JSON Schema when using "anyOf" with "requred"

I have a JSON Schema that allows object to have one or more properties:

"properties": {
  "alpha": {
    "$ref": "#/$defs/alpha"
  },
  "beta": {
    "$ref": "#/$defs/beta"
  }
},
"anyOf": [
  {
    "required": [
      "alpha"
    ]
  },
  {
    "required": [
      "beta"
    ]
  }
]

Using ajv compile with strict mode enabled to validate the schema itself, it fails validation. How can I fix it?


Update

Looks like this is a known issue and currently there is no way around it:


I've tried using anyOf on properties, but while this schema validates, it doesn't work as intended:

"anyOf": [
  {
    "properties": {
      "alpha": {
        "$ref": "#/$defs/alpha"
      }
    },
    "required": [
      "alpha"
    ]
  },
  {
    "properties": {
      "beta": {
        "$ref": "#/$defs/beta"
      }
    },
    "required": [
      "beta"
    ]
  }
]
Ajv command
ajv compile --spec=draft2020 --validate-formats=true --verbose --all-errors --strict=true -c ajv-formats -s repro.json
Ajv error
schema repro.json is invalid
error: strict mode: required property "beta" is not defined at "repro.json#/anyOf/0" (strictRequired)
Full JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$ref": "#/$defs/root",
  "$defs": {
    "root": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "alpha": {
          "$ref": "#/$defs/alpha"
        },
        "beta": {
          "$ref": "#/$defs/beta"
        }
      },
      "anyOf": [
        {
          "required": [
            "alpha"
          ]
        },
        {
          "required": [
            "beta"
          ]
        }
      ]
    },
    "alpha": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "foo": {
          "type": "string"
        }
      }
    },
    "beta": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "bar": {
          "type": "string"
        }
      }
    }
  }
}
JSON example
{
  "alpha": {
    "foo": "xyz"
  }
}

Upvotes: 1

Views: 3663

Answers (1)

Ether
Ether

Reputation: 53966

You need to disable strict mode, which thinks that any required keyword needs to have an adjacent properties for those properties.

Alternatively, you can move the properties definitions into the anyOf clauses -- but you'll have to repeat both of them in both sides, which is not so great (otherwise you could have both properties present but one of them not validate according to their schema).

So try this:

  "$defs": {
    "root": {
      "type": "object",
      "anyOf": [
        {
          "required": [
            "alpha"
          ],
          "properties": {
            "alpha": {
              "$ref": "#/$defs/alpha"
            },
            "beta": {
              "$ref": "#/$defs/beta"
            }
          },
          "additionalProperties": false,
        },
        {
          "required": [
            "beta"
          ],
          "properties": {
            "alpha": {
              "$ref": "#/$defs/alpha"
            },
            "beta": {
              "$ref": "#/$defs/beta"
            }
          },
          "additionalProperties": false
        }
      ]
    }
  },
  ...

Upvotes: 2

Related Questions