diff --git a/jsonschema-validation-output-machines.md b/jsonschema-validation-output-machines.md index 398162bb..e297fb9c 100644 --- a/jsonschema-validation-output-machines.md +++ b/jsonschema-validation-output-machines.md @@ -24,7 +24,27 @@ MAY deviate from this in their internal modelling, as supported by their specific languages and platforms, however it is RECOMMENDED that the output be convertible to the JSON format defined herein via serialization or other means. -## Minimum Information +## Applicability + +The formats described in this document apply only for a successful evaluation, +irrespective of whether validation passes or fails. If the implementation +encounters a scenario for which JSON Schema requires that evaluation halts, the +requirements herein do not apply, and the implementation SHOULD react as +appropriate for its language/environment. + +## Overview + +The root of JSON Schema output MUST be a JSON object. This object MUST contain +the following metadata regarding the validation: + +| JSON Property Name | Description | +|:-:|:-| +| `baseUri` | Evaluation root base URI (`$id` value) | +| `valid` | Boolean containing the overall validation result | +| `details` | Contains the detailed subschema evaluation results in one of the [formats](#output-structure) below
Required only for "list" and "hierarchical" formats | + + +## Minimum Information for Subschema Validation and Annotation Beyond the simplistic "flag" output, additional information is useful to aid in debugging evaluation of an instance by a schema. @@ -57,35 +77,12 @@ passed validation by the local subschema. The JSON key for these additional results is `valid`. -### Results from Subschemas - -Evaluation results generated by applying a subschema to the instance or a child -of the instance. Keywords which have multiple subschemas (e.g. `anyOf`) will -generally generate an output unit for each subschema. In order to accommodate -potentially multiple results, the value of this property MUST be an array of -output units, even if only a single output unit is produced. - -For "list", this property will appear only at the root output unit and will hold -all output units in a flat list. - -For "hierarchical", this property will contain results in a tree structure where -each output unit may itself have further nested results. - -The sequence of output units within this list is not specified and MAY be -determined by the implementation. Sets of output units are considered equivalent -if they contain the same units, in any order. - - - -The JSON key for these additional results is `details`. - ## Output Structure {#output-structure} This specification defines three output formats. -- **Flag** - A boolean which simply indicates the overall validation result with - no further details. -- **List** - Provides validation information in a flat list structure. +- **Flag** - Only the top-level overview needs to be populated; `details` is omitted. +- **List** - Provides all subschema results in a flat array. - **Hierarchical** - Provides validation information in a hierarchical structure that follows the evaluation paths generated while processing the schema. @@ -219,13 +216,13 @@ The passing instance will produce the following annotations: ### Flag -In the simplest case, merely the boolean result for the `valid` valid property -needs to be fulfilled. For this format, all other information is explicitly -omitted. +In the simplest case, only the overview needs to be fulfilled. For the "flag" +format, all other information is explicitly omitted. ```json "Flag Results" { - "valid": false + "baseUri": "https://json-schema.org/schemas/example", + "results": false } ``` @@ -237,14 +234,8 @@ check the other three. The logic can simply return with success. ### List -The "list" structure is a flat list of output units contained within a root -output unit. - -The root output unit contains `valid` for the overall result and `details` for -the list of specific results. All other information is explicitly omitted from -the root output unit. If the root schema produces errors or annotations, then -the output node for the root MUST be present within the root output unit's -`details` list with those errors or annotations. +The "list" format is a flat list of output units contained within a root output +unit. Output units which do not contain errors or annotations SHOULD be excluded from this format, however implementations MAY choose to include them for @@ -252,6 +243,7 @@ completeness. ```json "Failing Results" { + "baseUri": "https://json-schema.org/schemas/example", "valid": false, "details": [ { @@ -287,6 +279,7 @@ completeness. ```json "Passing Results" { + "baseUri": "https://json-schema.org/schemas/example", "valid": true, "details": [ { @@ -353,197 +346,210 @@ completeness. ### Hierarchical -The "Hierarchical" structure is a tree structure that follows the evaluation -path during the validation process. Typically, it will resemble the schema as if -all referenced schemas were inlined in place of their associated by-reference +The "hierarchical" format is a tree structure that follows the evaluation path +during the validation process. Typically, it will resemble the schema as if all +referenced schemas were inlined in place of their associated by-reference keywords. -All output units are included in this format. +For each output unit, evaluation results generated by any subschemas are +provided under a `details` property, and each such subschema will generate an +output unit. In order to accommodate keywords with multiple subschemas, the +value of this property MUST be an array of output units, even if only a single +output unit is produced. The sequence of output units within this list is not +specified and MAY be determined by the implementation. -The location properties of the root output unit MAY be omitted. +All output units are included in this format. ```json "failing Results { + "baseUri": "https://json-schema.org/schemas/example", "valid": false, - "evaluationPath": "", - "schemaLocation": "https://json-schema.org/schemas/example#", - "instanceLocation": "", - "details": [ - { - "valid": false, - "evaluationPath": "/properties/foo", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo", - "instanceLocation": "/foo", - "details": [ - { - "valid": false, - "evaluationPath": "/properties/foo/allOf/0", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/0", - "instanceLocation": "/foo", - "errors": { - "required": "Required properties [\"unspecified-prop\"] were not present" - } - }, - { - "valid": false, - "evaluationPath": "/properties/foo/allOf/1", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1", - "instanceLocation": "/foo", - "droppedAnnotations": { - "properties": [ "foo-prop" ], - "title": "foo-title" + "details": { + "valid": false, + "evaluationPath": "", + "schemaLocation": "https://json-schema.org/schemas/example#", + "instanceLocation": "", + "details": [ + { + "valid": false, + "evaluationPath": "/properties/foo", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo", + "instanceLocation": "/foo", + "details": [ + { + "valid": false, + "evaluationPath": "/properties/foo/allOf/0", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/0", + "instanceLocation": "/foo", + "errors": { + "required": "Required properties [\"unspecified-prop\"] were not present" + } }, - "details": [ - { - "valid": false, - "evaluationPath": "/properties/foo/allOf/1/properties/foo-prop", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/properties/foo-prop", - "instanceLocation": "/foo/foo-prop", - "errors": { - "const": "Expected \"1\"" + { + "valid": false, + "evaluationPath": "/properties/foo/allOf/1", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1", + "instanceLocation": "/foo", + "droppedAnnotations": { + "properties": [ "foo-prop" ], + "title": "foo-title" + }, + "details": [ + { + "valid": false, + "evaluationPath": "/properties/foo/allOf/1/properties/foo-prop", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/properties/foo-prop", + "instanceLocation": "/foo/foo-prop", + "errors": { + "const": "Expected \"1\"" + }, + "droppedAnnotations": { + "title": "foo-prop-title" + } }, - "droppedAnnotations": { - "title": "foo-prop-title" + { + "valid": true, + "evaluationPath": "/properties/foo/allOf/1/additionalProperties", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/additionalProperties", + "instanceLocation": "/foo/other-prop" } + ] + } + ] + }, + { + "valid": false, + "evaluationPath": "/properties/bar", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/bar", + "instanceLocation": "/bar", + "details": [ + { + "valid": false, + "evaluationPath": "/properties/bar/$ref", + "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar", + "instanceLocation": "/bar", + "droppedAnnotations": { + "properties": [ "bar-prop" ], + "title": "bar-title" }, - { - "valid": true, - "evaluationPath": "/properties/foo/allOf/1/additionalProperties", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/additionalProperties", - "instanceLocation": "/foo/other-prop" - } - ] - } - ] - }, - { - "valid": false, - "evaluationPath": "/properties/bar", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/bar", - "instanceLocation": "/bar", - "details": [ - { - "valid": false, - "evaluationPath": "/properties/bar/$ref", - "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar", - "instanceLocation": "/bar", - "droppedAnnotations": { - "properties": [ "bar-prop" ], - "title": "bar-title" - }, - "details": [ - { - "valid": false, - "evaluationPath": "/properties/bar/$ref/properties/bar-prop", - "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar/properties/bar-prop", - "instanceLocation": "/bar/bar-prop", - "errors": { - "minimum": "2 is less than or equal to 10" - }, - "droppedAnnotations": { - "title": "bar-prop-title" + "details": [ + { + "valid": false, + "evaluationPath": "/properties/bar/$ref/properties/bar-prop", + "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar/properties/bar-prop", + "instanceLocation": "/bar/bar-prop", + "errors": { + "minimum": "2 is less than or equal to 10" + }, + "droppedAnnotations": { + "title": "bar-prop-title" + } } - } - ] - } - ] - } - ] + ] + } + ] + } + ] + } } ``` ```json "Passing Results { - "valid": true, - "evaluationPath": "", - "schemaLocation": "https://json-schema.org/schemas/example#", - "instanceLocation": "", - "annotations": { - "title": "root", - "properties": [ - "foo", - "bar" - ] - }, - "details": [ - { - "valid": true, - "evaluationPath": "/properties/foo", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo", - "instanceLocation": "/foo", - "details": [ - { - "valid": true, - "evaluationPath": "/properties/foo/allOf/0", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/0", - "instanceLocation": "/foo" - }, - { - "valid": true, - "evaluationPath": "/properties/foo/allOf/1", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1", - "instanceLocation": "/foo", - "annotations": { - "title": "foo-title", - "properties": [ - "foo-prop" - ], - "additionalProperties": [ - "unspecified-prop" - ] - }, - "details": [ - { - "valid": true, - "evaluationPath": "/properties/foo/allOf/1/properties/foo-prop", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/properties/foo-prop", - "instanceLocation": "/foo/foo-prop", - "annotations": { - "title": "foo-prop-title" - } - }, - { - "valid": true, - "evaluationPath": "/properties/foo/allOf/1/additionalProperties", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/additionalProperties", - "instanceLocation": "/foo/unspecified-prop" - } - ] - } + "baseUri": "https://json-schema.org/schemas/example", + "valid": false, + "details": { + "valid": true, + "evaluationPath": "", + "schemaLocation": "https://json-schema.org/schemas/example#", + "instanceLocation": "", + "annotations": { + "title": "root", + "properties": [ + "foo", + "bar" ] }, - { - "valid": true, - "evaluationPath": "/properties/bar", - "schemaLocation": "https://json-schema.org/schemas/example#/properties/bar", - "instanceLocation": "/bar", - "details": [ - { - "valid": true, - "evaluationPath": "/properties/bar/$ref", - "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar", - "instanceLocation": "/bar", - "annotations": { - "title": "bar-title", - "properties": [ - "bar-prop" - ] + "details": [ + { + "valid": true, + "evaluationPath": "/properties/foo", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo", + "instanceLocation": "/foo", + "details": [ + { + "valid": true, + "evaluationPath": "/properties/foo/allOf/0", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/0", + "instanceLocation": "/foo" }, - "details": [ - { - "valid": true, - "evaluationPath": "/properties/bar/$ref/properties/bar-prop", - "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar/properties/bar-prop", - "instanceLocation": "/bar/bar-prop", - "annotations": { - "title": "bar-prop-title" + { + "valid": true, + "evaluationPath": "/properties/foo/allOf/1", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1", + "instanceLocation": "/foo", + "annotations": { + "title": "foo-title", + "properties": [ + "foo-prop" + ], + "additionalProperties": [ + "unspecified-prop" + ] + }, + "details": [ + { + "valid": true, + "evaluationPath": "/properties/foo/allOf/1/properties/foo-prop", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/properties/foo-prop", + "instanceLocation": "/foo/foo-prop", + "annotations": { + "title": "foo-prop-title" + } + }, + { + "valid": true, + "evaluationPath": "/properties/foo/allOf/1/additionalProperties", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/foo/allOf/1/additionalProperties", + "instanceLocation": "/foo/unspecified-prop" } - } - ] - } - ] - } - ] + ] + } + ] + }, + { + "valid": true, + "evaluationPath": "/properties/bar", + "schemaLocation": "https://json-schema.org/schemas/example#/properties/bar", + "instanceLocation": "/bar", + "details": [ + { + "valid": true, + "evaluationPath": "/properties/bar/$ref", + "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar", + "instanceLocation": "/bar", + "annotations": { + "title": "bar-title", + "properties": [ + "bar-prop" + ] + }, + "details": [ + { + "valid": true, + "evaluationPath": "/properties/bar/$ref/properties/bar-prop", + "schemaLocation": "https://json-schema.org/schemas/example#/$defs/bar/properties/bar-prop", + "instanceLocation": "/bar/bar-prop", + "annotations": { + "title": "bar-prop-title" + } + } + ] + } + ] + } + ] + } } ``` diff --git a/output/schema.json b/output/schema.json index 8487a290..0761f9e0 100644 --- a/output/schema.json +++ b/output/schema.json @@ -3,11 +3,21 @@ "$id": "https://json-schema.org/draft/next/output/schema", "description": "A schema that validates the minimum requirements for validation output", - "anyOf": [ - { "$ref": "#/$defs/flag" }, - { "$ref": "#/$defs/list" }, - { "$ref": "#/$defs/hierarchical" } - ], + "properties": { + "baseUri": { + "type": "string", + "format": "iri" + }, + "valid": { "type": "boolean" }, + "details": { + "anyOf": [ + { "$ref": "#/$defs/list" }, + { "$ref": "#/$defs/hierarchical" } + ] + } + }, + "requires": [ "baseUri", "valid" ], + "$defs": { "outputUnit":{ "properties": { @@ -18,7 +28,7 @@ }, "schemaLocation": { "type": "string", - "format": "uri" + "format": "iri" }, "instanceLocation": { "type": "string", @@ -75,21 +85,7 @@ "type": "array", "items": { "$ref": "#/$defs/outputUnit" } }, - "flag": { - "properties": { - "valid": { "type": "boolean" } - }, - "required": [ "valid" ] - }, - "list": { - "properties": { - "valid": { "type": "boolean" }, - "nested": { - "$ref": "#/$defs/outputUnitArray" - } - }, - "required": [ "valid", "nested" ] - }, + "list": { "$ref": "#/$defs/outputUnitArray" }, "hierarchical": { "$ref": "#/$defs/outputUnit" } } }