diff --git a/hyper-schema.json b/hyper-schema.json index 82cf32fa..fc51b1bc 100644 --- a/hyper-schema.json +++ b/hyper-schema.json @@ -2,57 +2,8 @@ "$schema": "http://json-schema.org/draft-08/hyper-schema#", "$id": "http://json-schema.org/draft-08/hyper-schema#", "title": "JSON Hyper-Schema", - "$defs": { - "schemaArray": { - "allOf": [ - { "$ref": "http://json-schema.org/draft-08/schema#/$defs/schemaArray" }, - { - "items": { "$ref": "#" } - } - ] - } - }, "allOf": [ { "$ref": "http://json-schema.org/draft-08/schema#" } ], "properties": { - "additionalItems": { "$ref": "#" }, - "additionalProperties": { "$ref": "#"}, - "dependencies": { - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "type": "array" } - ] - } - }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/$defs/schemaArray" } - ] - }, - "$defs": { - "additionalProperties": { "$ref": "#" } - }, - "definitions": { - "$comment": "Renamed to $defs, but retained here to ensure compatibility", - "additionalProperties": { "$ref": "#" } - }, - "patternProperties": { - "additionalProperties": { "$ref": "#" } - }, - "properties": { - "additionalProperties": { "$ref": "#" } - }, - "if": {"$ref": "#"}, - "then": {"$ref": "#"}, - "else": {"$ref": "#"}, - "allOf": { "$ref": "#/$defs/schemaArray" }, - "anyOf": { "$ref": "#/$defs/schemaArray" }, - "oneOf": { "$ref": "#/$defs/schemaArray" }, - "not": { "$ref": "#" }, - "contains": { "$ref": "#" }, - "propertyNames": { "$ref": "#" }, - "base": { "type": "string", "format": "uri-template" diff --git a/jsonschema-core.xml b/jsonschema-core.xml index 557f2747..1ad6b6d7 100644 --- a/jsonschema-core.xml +++ b/jsonschema-core.xml @@ -363,7 +363,7 @@ -
+
A JSON Schema document, or simply a schema, is a JSON document used to describe an instance. @@ -571,14 +571,10 @@ Authors of extensions to JSON Schema are encouraged to write their own - meta-schemas, which extend the existing meta-schemas using "allOf". + meta-schemas, which MAY extend the existing meta-schemas using "allOf". This extended meta-schema SHOULD be referenced using the "$schema" keyword, to - allow tools to follow the correct behaviour. - - - Note that the recursive nature of meta-schemas requires re-defining - recursive keywords in the extended meta-schema, as can be seen in - the JSON Hyper-Schema meta-schema. + allow tools to follow the correct behaviour. The "$recurse" keyword is + provided to facilitate this usage.
@@ -789,41 +785,137 @@
-
- - The "$ref" keyword is used to reference a schema, and provides the ability to - validate recursive structures through self-reference. - - - An object schema with a "$ref" property MUST be interpreted as a "$ref" reference. - The value of the "$ref" property MUST be a URI Reference. - Resolved against the current URI base, it identifies the URI of a schema to use. - All other properties in a "$ref" object MUST be ignored. - - - The URI is not a network locator, only an identifier. A schema need not be - downloadable from the address if it is a network-addressable URL, and - implementations SHOULD NOT assume they should perform a network operation when they - encounter a network-addressable URI. - +
- A schema MUST NOT be run into an infinite loop against a schema. For example, if two - schemas "#alice" and "#bob" both have an "allOf" property that refers to the other, - a naive validator might get stuck in an infinite recursive loop trying to validate - the instance. - Schemas SHOULD NOT make use of infinite recursive nesting like this; the behavior is - undefined. + Two keywords are provided for referencing one schema from another, and + for validating recursive structures through self-reference. + Both of these keywords behave as + in-place applicators, except that the schema + being applied is identified rather than appearing as all or part of the + keyword's value. + +
+ + The "$ref" keyword is used to reference a statically identified schema. + + + An object schema with a "$ref" property MUST be interpreted as a "$ref" + reference. The value of the "$ref" property MUST be a URI Reference. + Resolved against the current URI base, it identifies the URI of a schema + to use. All other properties in a "$ref" object MUST be ignored. + + + The URI is not a network locator, only an identifier. A schema need not be + downloadable from the address if it is a network-addressable URL, and + implementations SHOULD NOT assume they should perform a network operation + when they encounter a network-addressable URI. + + + A schema MUST NOT be run into an infinite loop against an instance. For + example, if two schemas "#alice" and "#bob" both have an "allOf" property + that refers to the other, a naive validator might get stuck in an infinite + recursive loop trying to validate the instance. Schemas SHOULD NOT make + use of infinite recursive nesting like this; the behavior is undefined. + +
+ +
+ + The "$recurse" keyword is used to construct extensible recursive schemas. + + + This keyword's value MUST be the boolean literal true. + + Future drafts may extend the usage with other values. The immediate + use case does not require any targets other than the entry point + root, and a regular fragment URI reference does not provide the + correct semantics. Should other values be added in the future, + it is expected that a boolean true value will remain an alias for + this original use case. + + + + The presence of this keyword with a boolean true value indicates that, + during processing, it MUST be treated as a reference to the root of the + schema document where processing + was initiated. The current base URI is not relevant to "$recurse". + + + This document, known as the entry point schema, is the schema document that + was initially supplied to the implementation, as opposed to schema documents + that were processed as a result of following a "$ref" reference. Note that + even if processing began at a subschema within a document, the "$recurse" + target MUST be the root schema. + + + Aside from the dynamic definition of the reference target, a "$recurse" + reference MUST behave identically to a "$ref" reference. + +
+ + Given the following schemas: + + + + +
+ + When an implementation begins processing with the + "https://example.com/base" schema, both the "local" and "recursive" + references resolve to "https://example.com/base". The entry point + schema and the schema being processed are the same. + + + However, when an implementation begins processing with the + "https://example.com/extension" schema, and processes the + "https://example.com/base" schema as a result of following the "$ref" + within the "extended" property, now the entry point schema is + "https://example.com/extension". + + + Therefore the "local" property's reference + still resolves to "https://example.com/base" while the "recursive" + property's reference now resolves to "https://example.com/extension". + This behavior remains the same even if the implementation begins processing + at "https://example.com/extension#/properties/extended". + +
+
- The use of URIs to identify remote schemas does not necessarily mean anything is downloaded, - but instead JSON Schema implementations SHOULD understand ahead of time which schemas they will be using, - and the URIs that identify them. + The use of URIs to identify remote schemas does not necessarily mean + anything is downloaded, but instead JSON Schema implementations SHOULD + understand ahead of time which schemas they will be using, and the URIs + that identify them. - When schemas are downloaded, - for example by a generic user-agent that doesn't know until runtime which schemas to download, - see Usage for Hypermedia. + When schemas are downloaded, for example by a generic user-agent that + doesn't know until runtime which schemas to download, see + Usage for Hypermedia. Implementations SHOULD be able to associate arbitrary URIs with an arbitrary @@ -849,8 +941,8 @@ If the resulting URI identifies a schema within the current document, or - within another schema document that has been made available to the implementation, - then that schema SHOULD be used automatically. + within another schema document that has been made available to the + implementation, then that schema SHOULD be used automatically. For example, consider this schema: @@ -1006,7 +1098,8 @@
-
+
These keywords apply subschemas to the same location in the instance as the parent schema is being applied. They allow combining @@ -1644,6 +1737,7 @@ User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0 Moved "definitions" from the Validation specification here as "$defs" Moved applicator keywords from the Validation specification as their own vocabulary Moved "dependencies" from the Validation specification, but only the schema form + Added "$recurse" for dynamically evaluated recursive references diff --git a/schema.json b/schema.json index 182eefb0..1442d1b2 100644 --- a/schema.json +++ b/schema.json @@ -6,7 +6,7 @@ "schemaArray": { "type": "array", "minItems": 1, - "items": { "$ref": "#" } + "items": { "$recurse": true } }, "nonNegativeInteger": { "type": "integer", @@ -50,18 +50,22 @@ "type": "string", "format": "uri-reference" }, + "$recurse": { + "type": "boolean", + "const": true + }, "$comment": { "type": "string" }, "$defs": { "type": "object", - "additionalProperties": { "$ref": "#" }, + "additionalProperties": { "$recurse": true }, "default": {} }, "definitions": { "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.", "type": "object", - "additionalProperties": { "$ref": "#" }, + "additionalProperties": { "$recurse": true }, "default": {} }, "title": { @@ -101,10 +105,10 @@ "type": "string", "format": "regex" }, - "additionalItems": { "$ref": "#" }, + "additionalItems": { "$recurse": true }, "items": { "anyOf": [ - { "$ref": "#" }, + { "$recurse": true }, { "$ref": "#/$defs/schemaArray" } ], "default": true @@ -115,19 +119,19 @@ "type": "boolean", "default": false }, - "contains": { "$ref": "#" }, + "contains": { "$recurse": true }, "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, "required": { "$ref": "#/$defs/stringArray" }, - "additionalProperties": { "$ref": "#" }, + "additionalProperties": { "$recurse": true }, "properties": { "type": "object", - "additionalProperties": { "$ref": "#" }, + "additionalProperties": { "$recurse": true }, "default": {} }, "patternProperties": { "type": "object", - "additionalProperties": { "$ref": "#" }, + "additionalProperties": { "$recurse": true }, "propertyNames": { "format": "regex" }, "default": {} }, @@ -135,12 +139,12 @@ "type": "object", "additionalProperties": { "anyOf": [ - { "$ref": "#" }, + { "$recurse": true }, { "$ref": "#/$defs/stringArray" } ] } }, - "propertyNames": { "$ref": "#" }, + "propertyNames": { "$recurse": true }, "const": true, "enum": { "type": "array", @@ -162,13 +166,13 @@ "format": { "type": "string" }, "contentMediaType": { "type": "string" }, "contentEncoding": { "type": "string" }, - "if": {"$ref": "#"}, - "then": {"$ref": "#"}, - "else": {"$ref": "#"}, + "if": {"$recurse": true}, + "then": {"$recurse": true}, + "else": {"$recurse": true}, "allOf": { "$ref": "#/$defs/schemaArray" }, "anyOf": { "$ref": "#/$defs/schemaArray" }, "oneOf": { "$ref": "#/$defs/schemaArray" }, - "not": { "$ref": "#" } + "not": { "$recurse": true } }, "default": true }