Matioski
Matioski

Reputation: 157

JSON Schema Draft 7 issue in validating required property in array object

I have this JSON Schema file (shrinked to not show stuff not related to the question) :

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "urn:jsonschema:testing:frmwk",
  "type": "object",
  "title": "The root schema",
  "default": {},
  "required": [
    "processOrder"
  ],
  "additionalProperties": true,
  "properties": {
    "processOrder": {
      "$id": "#processOrder",
      "type": "array",
      "title": "The processOrder schema",
      "default": [],
      "additionalItems": true,
      "items": {
        "anyOf": [
          {
            "$id": "#0",
            "type": "object",
            "title": "The first anyOf schema",
            "default": {},
            "additionalProperties": true,
            "properties": {
              "cleanHistory": {
                "$id": "#cleanHistory",
                "type": "object",
                "title": "The cleanHistory schema",
                "default": {},
                "additionalProperties": true,
                "properties": {}
              }
            }
          },
          {
            "$id": "#3",
            "type": "object",
            "title": "The fourth anyOf schema",
            "default": {},
            "additionalProperties": true,
            "properties": {
              "processEvents": {
                "$id": "#processEvents",
                "type": "object",
                "title": "The processEvents schema",
                "default": {},
                "required": [
                  "identityTrigger"
                ],
                "additionalProperties": true,
                "properties": {
                  "identityTrigger": {
                    "$id": "#identityTrigger",
                    "type": "string",
                    "title": "The identityTrigger schema",
                    "default": ""
                  }
                }
              }
            }
          }
        ],
        "$id": "#items"
      }
    }
  }
}

The JSON I want to validate is :

{
  "description": "description",
  "requesteeName": "05300005",
  "processOrder": [
  {"cleanHistory": {} },
    {"processEvents": {
      "identityTrigger": "some trigger"
    }}
  ],
  "deleteObjects": "true"
}

Now, I'm expecting it to fail when I remove the string:

"identityTrigger": "some trigger"

because the "identityTrigger" property is in the required array in the processEvents object. But it is not failing, something has to be wrong in the array matching (processOrder array). Could someone give me an advice? Thanks

Upvotes: 0

Views: 1631

Answers (2)

Matioski
Matioski

Reputation: 157

I have managed to understand better how it works, as @Carsten said in the comment the anyOf with the single items without required properties was not working because any item with any property would have been validated. The correct schema would be(in bold the changes):

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "urn:jsonschema:testing:frmwk",
  "type": "object",
  "title": "The root schema",
  "default": {},
  "required": [
    "processOrder"
  ],
  "additionalProperties": true,
  "properties": {
    "processOrder": {
      "$id": "#processOrder",
      "type": "array",
      "title": "The processOrder schema",
      "default": [],
      "additionalItems": false,
      "items": {
        "anyOf": [
          {
            "$id": "#0",
            "type": "object",
            "title": "The first anyOf schema",
            "default": {},
            "additionalProperties": true,
            "required": ["cleanHistory"],
            "properties": {
              "cleanHistory": {
                "$id": "#cleanHistory",
                "type": "object",
                "title": "The cleanHistory schema",
                "default": {},
                "additionalProperties": true,
                "properties": {}
              }
            }
          },
          {
            "$id": "#3",
            "type": "object",
            "title": "The fourth anyOf schema",
            "default": {},
            "additionalProperties": true,
            "required": ["processEvents"],
            "properties": {
              "processEvents": {
                "$id": "#processEvents",
                "type": "object",
                "title": "The processEvents schema",
                "default": {},
                "required": [
                  "identityTrigger"
                ],
                "additionalProperties": true,
                "properties": {
                  "identityTrigger": {
                    "$id": "#identityTrigger",
                    "type": "string",
                    "title": "The identityTrigger schema",
                    "default": ""
                  }
                }
              }
            }
          }
        ],
        "$id": "#items"
      }
    }
  }
}

the main changes are 2:

  1. Added "additionalItems": false in the array object definition
  2. Added "required": ["cleanHistory"] and "required": ["processEvents"] for each correspondent root properties item, in my case ("cleanHistory" and "processEvents") in this way the AnyOf will force to use one of the schema listed to validate the items in the array.

Upvotes: 0

Carsten
Carsten

Reputation: 2147

The reason for the still-successful validation was the fact that the first anyOf option did not specify any required properties while allowing any additionalProperties, therefore an empty JSON Object was always valid against this first option. The fix is to expect at least one property in each anyOf to avoid an empty object being valid against any of them.

However, there seem to be some additional points here that would benefit from clarification:

  1. The additionalProperties keyword is by default true and does not need to be mentioned in that case. As per json-schema.org:

    The additionalProperties keyword is used to control the handling of extra stuff, that is, properties whose names are not listed in the properties keyword. By default any additional properties are allowed.

  2. The additionalItems keyword only applies if items is an array (i.e. the array is a tuple of different types at specific positions). As per json-schema.org:

    When items is a single schema, the additionalItems keyword is meaningless, and it should not be used.

  3. Your default values are empty objects, which are invalid against the described structure with required properties. Best to leave those default values out as well then – unless that is just because you removed their contents in the scope of this question here to keep it simple.

Upvotes: 2

Related Questions