unevaluatedItems : Schema

unevaluatedItems

Schema

Validates array elements that did not successfully validate against other standard array applicators.

Value This keyword must be set to a valid JSON Schema
Kind Applicator Annotation
Applies To Array
Dialect 2020-12
Introduced In 2019-09
Vocabulary Unevaluated
Specification https://json-schema.org/draft/2020-12/json-schema-core.html#section-11.2
Metaschema https://json-schema.org/draft/2020-12/meta/unevaluated
Official Tests draft2020-12/unevaluatedItems.json
Default {}
Annotation Boolean A boolean true if it applied to any item of the instance
Affected By
Affects None
Also See

If no relevant annotations are present, the unevaluatedItems subschema must be applied to all locations in the array. If a boolean true value is present from any of the relevant annotations, unevaluatedItems is ignored. Otherwise, the subschema must be applied to any index greater than the largest annotation value for prefixItems, which does not appear in any annotation value for contains.

Evaluation

It’s crucial to understand what evaluation means in this context.

unevaluatedItems considers annotations from prefixItems, items, and contains, both as adjacent keywords and in subschemas of adjacent keywords. Additionally, it is also affected by other unevaluatedItems in nested schemas (if present).

  • The keywords prefixItems, items, contains and unevaluatedItems produce annotations for the indexes they successfully validate against.
  • If any of these keywords generate an annotation for a particular index, that index is considered as evaluated.
  • By definition, the unevaluatedItems subschema is always applied after prefixItems, items, and contains subschemas.
  • As its name implies, unevaluatedItems applies to any array index that has not been previously evaluated.

Examples

Schema with 'unevaluatedItems' set to boolean true Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "unevaluatedItems": true
}
Valid All array instances pass against the true schema Instance
[ "foo", "bar" ]
Annotations
{ "keyword": "/unevaluatedItems", "instance": "", "value": "true" }
Valid 'unevaluatedItems' does not have any effect on instances other than an array Instance
"John Doe"
  • Here, no items are defined in the above schema. Consequently, all items in an array instance are considered unevaluated, and the unevaluatedItems subschema applies to them. Since the subschema here is a boolean true, an instance with unevaluated items, regardless of their value, is considered valid.
Schema with 'unevaluatedItems' set to boolean false Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "unevaluatedItems": false
}
Invalid All object instances fail against the false schema Instance
[ "foo", "bar" ]
Valid 'unevaluatedItems' does not have any effect on instances other than an array Instance
{ "John": 46 }
Schema with 'unevaluatedItems', 'prefixItems', and 'contains', with unevaluatedItems set to boolean false Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "prefixItems": [ { "type": "string" } ],
  "contains": { "type": "number" },
  "unevaluatedItems": false
}
Invalid An array instance with unevaluated items is invalid Instance
[ "foo", 101, false ]
Valid An array instance with no unevaluated items is valid Instance
[ "foo", 101, 77 ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 0 }
{ "keyword": "/contains", "instance": "", "value": [ 1, 2 ] }
  • For the first instance, the annotation result of prefixItems is 0, and the annotation result of contains is [ 1 ]. However, the item at 2nd index (i.e., false) remains unevaluated, so the unevaluatedItems subschema applies to it. This subschema fails (as any instance against a false schema is always invalid), leading to validation failure.

  • For the second instance, the annotation result of prefixItems is 0, and the annotation result of contains is [ 1, 2 ]. No items remain unevaluated; hence, the instance is considered valid.

Schema with 'unevaluatedItems', 'prefixItems', and 'contains', with unevaluatedItems set to an object schema Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "prefixItems": [ { "type": "string" } ],
  "contains": { "type": "number" },
  "unevaluatedItems": { "type": "boolean" }
}
Valid An array instance with no unevaluated items is valid Instance
[ "foo", 101, 77 ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 0 }
{ "keyword": "/contains", "instance": "", "value": [ 1, 2 ] }
Valid An array instance with unevaluated items that conform to the 'unevaluatedItems' subschema is valid Instance
[ "foo", 101, false ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 0 }
{ "keyword": "/contains", "instance": "", "value": [ 1 ] }
{ "keyword": "/unevaluatedItems", "instance": "", "value": true }
Invalid An array instance with unevaluated items that do not conform to the 'unevaluatedItems' subschema is invalid Instance
[ "foo", 101, [ false ] ]
  • For the first instance, there are no unevaluated items.

  • For the second instance, the item at 2nd index (i.e., false) remains unevaluated, and the unevaluatedItems subschema applies to it. This item conforms to this subschema, and hence the instance is valid.

Schema with 'unevaluatedItems', and 'allOf' keyword Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "prefixItems": [ { "type": "string" } ],
  "allOf" : [
    {
      "prefixItems": [
        true,
        { "type": "boolean" }
      ]
    }
  ],
  "unevaluatedItems": { "type": "number" }
}
Valid An array instance with unevaluated items that conform to the 'unevaluatedItems' subschema is valid Instance
[ "foo", false, 22 ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 0 }
{ "keyword": "/allOf/0/prefixItems", "instance": "", "value": 1 }
{ "keyword": "/unevaluatedItems", "instance": "", "value": true }
Invalid An array instance with unevaluated items that do not conform to the 'unevaluatedItems' subschema is invalid Instance
[ "foo", 101, [ false ] ]

For the above two instances, the annotation result of top level prefixItems is 0, and the annotation result of the nested prefixItems is 1. The unevaluatedItems recognizes the annotations from top level prefixItems as well as nested prefixItems (as it can see through adjacent and nested applicators as only the produced annotations matter, not the schema structure) and ensures that the item at index 2 remains unevaluated and its subschema applies to it.

  • The first instance passes as it conforms to the unevaluated subschema.
  • The second instance fails as it does not conform to the unevaluated subschema.
Schema with 'unevaluatedItems', and 'allOf' keyword Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "prefixItems": [ { "type": "string" } ],
  "allOf" : [
    {
      "items": true
    }
  ],
  "unevaluatedItems": { "type": "number" }
}
Valid An array instance with no unevaluated items is valid Instance
[ "foo", false, 22 ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 0 }
{ "keyword": "/allOf/0/items", "instance": "", "value": true }
  • Here, the nested items evaluated all the unevaluated items. So there’s nothing left unevaluated.
Schema with 'unevaluatedItems' and '#ref' keyword Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "prefixItems": [
    { "type": "string" },
    { "type": "boolean" }
  ],
  "$ref": "#/$defs/bar",
  "unevaluatedItems": false,
  "$defs": {
    "bar": {
      "contains": { "type": "number" }
    }
  }
}
Valid An instance with no unevaluated items is valid Instance
[ "foo", false, 22 ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 1 }
{ "keyword": "/$ref/contains", "instance": "", "value": [ 2 ] }
Invalid An instance with unevaluated items is invalid Instance
[ "foo", false, "bar" ]
Schema with nested 'unevaluatedItems' keyword Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "prefixItems": [ { "type": "string" } ],
  "allOf" : [
    {
      "unevaluatedItems": true
    }
  ],
  "unevaluatedItems": false
}
Valid No items left unevaluated for the top level 'unevaluatedItems' Instance
[ "foo", false, "bar" ]
Annotations
{ "keyword": "/prefixItems", "instance": "", "value": 0 }
{ "keyword": "/allOf/0/unevaluatedItems", "instance": "", "value": true }