diff --git a/content/2019-09/format/format.markdown b/content/2019-09/format/format.markdown index d75ff07f..34833601 100644 --- a/content/2019-09/format/format.markdown +++ b/content/2019-09/format/format.markdown @@ -20,8 +20,9 @@ annotation: kind: [ "string" ] --- -The `format` keyword communicates that string instances are of the given -logical type by producing an annotation value. +The [`format`]({{< ref "2019-09/format/format" >}}) keyword communicates that +string instances are of the given logical type by producing an annotation +value. {{}} By default, this keyword does not perform validation, as validating formats is considered optional by the official JSON Schema Test diff --git a/content/draft6/core/id.markdown b/content/draft6/core/id.markdown index 3c9538ad..85de0790 100644 --- a/content/draft6/core/id.markdown +++ b/content/draft6/core/id.markdown @@ -18,3 +18,165 @@ related: - vocabulary: core keyword: $schema --- + +The [`$id`]({{< ref "draft6/core/id" >}}) keyword explicitly turns a schema +into a _schema resource_ (a schema that is associated with a URI). Relative +URIs are resolved against the _current_ base URI, which is either the closest +parent [`$id`]({{< ref "draft6/core/id" >}}) keyword (applicable in the case +of compound schemas), or the base URI as determined by the context on which the +schema is declared (i.e. serving a schema over HTTP _may_ implicitly award it +such URL as the base). + +{{}} + +This keyword directly applies (without modifications or extensions) the concept +of URIs to schemas. **If you are having a hard time following the concepts +discussed in this page, it is probably because you don't have a strong grasp of +URIs yet** (a notably hard but universal pre-requisite!). + +To learn more about URIs, we strongly suggest studying the [IETF RFC +3986](https://www.rfc-editor.org/info/rfc3986) URI standard. To avoid +confusion, note that there is also a [WHATWG URL +Standard](https://url.spec.whatwg.org) that targets URLs in the context of web +browsers. However, JSON Schema only implements and expects the IETF original +standard. + +{{}} + +{{}} + +In JSON Schema, schema identifiers are merely identifiers and no behaviour is +imposed on them. In particular, JSON Schema does not guarantee that a schema +with an HTTP URL identifier is actually resolvable at such URL. To avoid +surprises, JSON Schema implementations must be careful with automatically +sending remote network requests when encountering supposely resolvable schema +identifiers. + +{{}} + +{{}} + +It is strongly recommended for every schema file to explicitly declare an +_absolute_ URI using this keyword. By doing so, you completely avoid various +complex URI resolution edge cases, mainly when the base URI is implicit and +context-dependent. + +If you are serving schemas over the network (i.e. over HTTP), it is common to +set this keyword to the target URL. However, if your schemas are not accessible +over the network, prefer using a +[URN](https://en.wikipedia.org/wiki/Uniform_Resource_Name) (with a valid +namespace registered by +[IANA](https://www.iana.org/assignments/urn-namespaces/urn-namespaces.xhtml)) +or a non-locatable URI scheme such as a [Tag URI](https://www.taguri.org). + +{{}} + +To debug the role of the [`$id`]({{< ref "draft6/core/id" >}}) keyword on +a schema (particularly schemas with embedded resources), try the [`jsonschema +inspect`](https://github.com/sourcemeta/jsonschema/blob/main/docs/inspect.markdown) +command. This command prints detailed information about each schema resource, +subschema, location, and reference present in the schema. For example: + +```sh +$ jsonschema inspect schema.json +(RESOURCE) URI: https://example.com/schema + Type : Static + Root : https://example.com/schema + Pointer : + Base : https://example.com/schema + Relative Pointer : + Dialect : http://json-schema.org/draft-06/schema# + Base Dialect : http://json-schema.org/draft-06/schema# + Parent : + Instance Location : + +... + +(SUBSCHEMA) URI: https://example.com/schema#/properties/foo + Type : Static + Root : https://example.com/schema + Pointer : /properties/foo + Base : https://example.com/schema + Relative Pointer : /properties/foo + Dialect : http://json-schema.org/draft-06/schema# + Base Dialect : http://json-schema.org/draft-06/schema# + Parent : + Instance Location : /foo + +... + +(REFERENCE) ORIGIN: /$schema + Type : Static + Destination : http://json-schema.org/draft-06/schema + - (w/o fragment) : http://json-schema.org/draft-06/schema + - (fragment) : +``` + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/schemas/even-number.json", + "type": "number", + "multipleOf": 2 +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "tag:example.com,2025:even-number", + "type": "number", + "multipleOf": 2 +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "urn:example:even-number", + "type": "number", + "multipleOf": 2 +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/schemas/user.json", + "type": "object", + "properties": { + "name": { "$ref": "#nonEmptyString" }, + "email": { "$ref": "#nonEmptyString" } + }, + "definitions": { + "nonEmptyString": { + "$id": "#nonEmptyString", + "type": "string", + "minLength": 1 + } + } +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/schemas/root.json", + "properties": { + "foo": { + "$id": "foo.json" + }, + "bar": { + "$id": "/schemas/bar.json" + }, + "baz": { + "$id": "https://absolute.example/baz.json", + "items": { + "$id": "deep" + } + } + } +} +{{}} diff --git a/content/draft6/core/ref.markdown b/content/draft6/core/ref.markdown index 156b6658..7cfad708 100644 --- a/content/draft6/core/ref.markdown +++ b/content/draft6/core/ref.markdown @@ -21,3 +21,211 @@ related: - vocabulary: validation keyword: definitions --- + +The [`$ref`]({{< ref "draft6/core/ref" >}}) keyword enables a schema to +reference another schema by its URI, effectively importing its keywords into the +current evaluation process. This keyword is the cornerstone of schema +composition, allowing complex schemas to be created out of simpler ones. A +reference may set its URI fragment to a [JSON +Pointer](https://www.rfc-editor.org/rfc/rfc6901) that determines the destination +of the reference after first resolving the rest of the URI. + +{{}} + +In JSON Schema [Draft 7](/draft7) and earlier versions, **any subschema +declaring the [`$ref`]({{< ref "draft6/core/ref" >}}) keyword is considered to +be a _reference object_ and any other sibling keyword is silently ignored**. As +a consequence, subschemas with references that make use of other keywords must +artificially wrap the reference into its own subschema using keywords like +[`allOf`]({{< ref "draft6/validation/allof" >}}). + +{{}} + +{{}} + +**Avoid referencing other schema files using their file paths**. While some +implementations support this by automatically constructing schema URIs that +make use of the `file://` scheme, this is not enforced behaviour. The only +standard and guaranteed mechanism of declaring a schema URI for identification +and referencing purposes is through the [`$id`]({{< ref "draft6/core/id" >}}) keyword. + +{{}} + +{{}} + +The target of a reference must be a schema. Referencing a JSON value that is +not unambiguously recognised as a schema leads to undefined behaviour. This +not only includes referencing arbitrary JSON files (the obvious case), but +also referencing parts of a schema that a JSON Schema evaluator does not +consider to be a subschema. For example, referencing the contents of the +[`examples`]({{< ref "draft6/validation/examples" >}}) keyword. + +{{}} + +References are either _internal_ (pointing at schemas within the same schema +definition) or _external_ (pointing at schema resources outside the given schema +definition). If the reference is a relative URI, it is resolved against the +_current_ base URI, which is either the closest parent URI as set by the +[`$id`]({{< ref "draft6/core/id" >}}) keyword, or the base URI as determined by +the context on which the schema is declared. Schema wrappers like OpenAPI are +notable examples of the latter. A relative reference from a schema embedded in +an OpenAPI specification is resolved from the root of the API specification, and +not from the root of the schema. + +{{}} + +It is highly recommended to make use of _external_ references to break down +complex monolithic schemas into smaller schema files. However, for performance +and integrity reasons, avoid resolving these external schemas (i.e. over HTTP +or the filesystem) at runtime. + +You can automatically inline external references at build time using the +[`jsonschema +bundle`](https://github.com/sourcemeta/jsonschema/blob/main/docs/bundle.markdown) +command. + +{{}} + +Note that a reference to an absolute URI does not necessarily mean that the +reference is external. Conversely, a reference to a relative URI does not +necessarily mean that the reference is internal. When encountering any type +of reference, a JSON Schema implementation will check if the root schema +resource or its nested schema resources (if any) declare the canonically +resolved version of such URI through the [`$id`]({{< ref "draft6/core/id" +>}}) keyword. If so, the reference is considered internal. This +internal-first lookup is what enables the standard +[bundling](https://json-schema.org/blog/posts/bundling-json-schema-compound-documents) +process. + +{{}} + +If you are having a hard time understanding references and some of its more +subtle scenarios (like base URI resolution), it is probably because you don't +have a strong grasp of URIs yet (a notably hard but universal +pre-requisite!). + +To learn more about URIs, we strongly suggest studying the [IETF RFC +3986](https://www.rfc-editor.org/info/rfc3986) URI standard. To avoid +confusion, note that there is also a [WHATWG URL +Standard](https://url.spec.whatwg.org) that targets URLs in the context of +web browsers. However, JSON Schema only implements and expects the IETF +original standard. As a notable extension, this keyword supports referencing +specific parts of a schema through the use of a JSON Pointer, so we also +recommend studying the [IETF RFC 6901](https://www.rfc-editor.org/info/rfc6901) +JSON Pointer standard and its [URI fragment identifier +representation](https://www.rfc-editor.org/rfc/rfc6901#section-6). + +{{}} + +To debug references and how JSON Schema is interpreting your relative URIs, +try the [`jsonschema +inspect`](https://github.com/sourcemeta/jsonschema/blob/main/docs/inspect.markdown) +command. This command prints detailed information about each schema reference +and of each location of the schema. For example: + +```sh +$ jsonschema inspect schema.json +... + +(REFERENCE) ORIGIN: /properties/foo/$ref + Type : Static + Destination : https://example.com/schemas/example#/definitions/uuid + - (w/o fragment) : https://example.com/schemas/example + - (fragment) : /definitions/uuid + +... +``` + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "foo": { + "type": "string", + "$ref": "#/definitions/test" + } + }, + "definitions": { + "test": { "minLength": 2 } + } +} +{{}} + +{{}} +12345 +{{}} + +{{}} +"foo" +{{}} + +{{}} +"x" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/my-schema", + "properties": { + "byRelativeFragmentPointer": { + "$ref": "#/definitions/helper" + }, + "byAbsoluteFragmentPointer": { + "$ref": "https://example.com/my-schema#/definitions/helper" + }, + "byRelativeURI": { + "$ref": "my-helper" + }, + "byRelativeRootPathURI": { + "$ref": "/my-helper" + }, + "byRelativeBackslashURI": { + "$ref": "my-schema/../my-helper" + }, + "byAbsoluteURI": { + "$ref": "https://example.com/my-helper" + } + }, + "definitions": { + "helper": { + "$id": "my-helper", + "type": "string" + } + } +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/my-schema", + "properties": { + "byAbsoluteURI": { + "$ref": "https://example.com/my-other-schema" + }, + "byRelativeURI": { + "$ref": "my-other-schema" + }, + "byRelativeRootPathURI": { + "$ref": "/my-other-schema" + }, + "byRelativeBackslashURI": { + "$ref": "my-schema/../my-other-schema" + } + } +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "byAbsoluteURI": { + "$ref": "urn:example:my-other-schema" + } + } +} +{{}} diff --git a/content/draft6/core/schema.markdown b/content/draft6/core/schema.markdown index 33d2724c..4714f5ae 100644 --- a/content/draft6/core/schema.markdown +++ b/content/draft6/core/schema.markdown @@ -17,3 +17,134 @@ related: - vocabulary: validation keyword: definitions --- + +The [`$schema`]({{< ref "draft6/core/schema" >}}) keyword serves to explicitly +associate a _schema resource_ with the JSON Schema dialect that defines it, +where the dialect is the identifier of a meta-schema that defines the keywords +in use and imposes syntactic constraints on its schema instances. If the +[`$schema`]({{< ref "draft6/core/schema" >}}) keyword is not declared, the +schema inherits its context-specific or implementation-specific default +dialect. + +{{}} It is common to avoid the [`$schema`]({{< ref "draft6/core/schema" >}}) keyword when working with +[OpenAPI](https://www.openapis.org). This is possible because the OpenAPI +specification clearly documents what the default JSON Schema dialect is for +every version. For example, [OpenAPI +v3.1.1](https://spec.openapis.org/oas/latest.html#json-schema-keywords) defines +the default dialect as `https://spec.openapis.org/oas/3.1/dialect/base`. +{{}} + +Strictly-compliant JSON Schema implementations will refuse to process a schema +whose dialect cannot be unambiguously determined. + +{{}} To avoid undefined behavior, it is generally recommended to +always explicitly set the dialect of a schema using the [`$schema`]({{< ref "draft6/core/schema" >}}) keyword. This ensures that less strict +implementations unambiguously know how to process the schema and don't attempt +to guess.{{}} + +Note that the [`$schema`]({{< ref "draft6/core/schema" >}}) keyword can occur +multiple times in the same schema, and not only at the top-level. This is often +the case when performing [JSON Schema +Bundling](https://github.com/sourcemeta/jsonschema/blob/main/docs/bundle.markdown) +to inline externally referenced schemas that might be based on different +dialects of JSON Schema. + +{{}}JSON Schema prohibits referencing meta-schemas using +relative URIs. The fundamental reason for this is that resolving the +meta-schema is necessary for correctly determining the base URI of the schema, +from which a relative meta-schema reference would be resolved, introducing a +circular problem. + +A common occurrence of this issue is setting the [`$schema`]({{< ref "draft6/core/schema" >}}) keyword to a relative path, which is again invalid +according to the specification.{{}} + +{{}}JSON Schema prohibits the use of the this keyword on +arbitrary subschemas that do not represent schema resources. It can only be +present at the root of the schema (an implicit schema resource) or as a sibling +of the [`$id`]({{< ref "draft6/core/id" >}}) keyword (an explicit schema +resource).{{}} + +A schema is considered syntactic valid if it successfully validates against its +dialect meta-schema. You can validate a schema against its meta-schema using +the [`jsonschema +metaschema`](https://github.com/sourcemeta/jsonschema/blob/main/docs/metaschema.markdown) +command. For example: + +```sh +$ jsonschema metaschema my-schema.json +``` + +To debug the role of the [`$schema`]({{< ref "draft6/core/schema" >}}) +keyword on a schema (particularly schemas with embedded resources), try the +[`jsonschema +inspect`](https://github.com/sourcemeta/jsonschema/blob/main/docs/inspect.markdown) +command. This command prints detailed information about each schema resource, +subschema, location, and reference present in the schema. For example: + +```sh +$ jsonschema inspect schema.json +(RESOURCE) URI: https://example.com/schema + Type : Static + Root : https://example.com/schema + Pointer : + Base : https://example.com/schema + Relative Pointer : + Dialect : http://json-schema.org/draft-06/schema# + Base Dialect : http://json-schema.org/draft-06/schema# + Parent : + Instance Location : + +... + +(SUBSCHEMA) URI: https://example.com/schema#/properties/foo + Type : Static + Root : https://example.com/schema + Pointer : /properties/foo + Base : https://example.com/schema + Relative Pointer : /properties/foo + Dialect : http://json-schema.org/draft-06/schema# + Base Dialect : http://json-schema.org/draft-06/schema# + Parent : + Instance Location : /foo + +... + +(REFERENCE) ORIGIN: /$schema + Type : Static + Destination : http://json-schema.org/draft-06/schema + - (w/o fragment) : http://json-schema.org/draft-06/schema + - (fragment) : +``` + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "string" +} +{{}} + +{{}} +{ + "items": [ { "type": "number" } ] +} +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "price": { "type": "number" }, + "discount": { + "$ref": "#/definitions/discount" + } + }, + "definitions": { + "discount": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "number" + } + } +} +{{}} diff --git a/content/draft6/validation/additionalItems.markdown b/content/draft6/validation/additionalItems.markdown index 2e8cfe03..97a991dd 100644 --- a/content/draft6/validation/additionalItems.markdown +++ b/content/draft6/validation/additionalItems.markdown @@ -26,3 +26,100 @@ related: - vocabulary: validation keyword: uniqueItems --- + +The [`additionalItems`]({{< ref "draft6/validation/additionalitems" >}}) +keyword restricts array instance items not described by the _sibling_ +[`items`]({{< ref "draft6/validation/items" >}}) keyword (when [`items`]({{< +ref "draft6/validation/items" >}}) is in array form), to validate against the +given subschema. + +{{}}This keyword **only** has an effect when the sibling +[`items`]({{< ref "draft6/validation/items" >}}) keyword is set to an array of +schemas. If [`items`]({{< ref "draft6/validation/items" >}}) is not present or +is set to a schema (not an array of schemas), [`additionalItems`]({{< ref +"draft6/validation/additionalitems" >}}) has no effect and is +ignored.{{}} + +{{}}This keyword does not prevent an array instance from being +empty or having fewer items than the [`items`]({{< ref +"draft6/validation/items" >}}) array. If needed, use the [`minItems`]({{< ref +"draft6/validation/minitems" >}}) keyword to assert on the minimum bounds of the +array.{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": [ { "type": "boolean" }, { "type": "number" } ], + "additionalItems": { "type": "string" } +} +{{}} + +{{}} +[ false, 35 ] +{{}} + +{{}} +[ false, 35, "foo", "bar" ] +{{}} + +{{}} +[ false, 35, { "foo": "bar" } ] +{{}} + +{{}} +[] +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": [ { "type": "boolean" }, { "type": "number" } ], + "additionalItems": false +} +{{}} + +{{}} +[ false, 35 ] +{{}} + +{{}} +[ false, 35, "foo" ] +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": { "type": "number" }, + "additionalItems": { "type": "string" } +} +{{}} + +{{}} +[ 1, 2, 3 ] +{{}} + +{{}} +[ 1, 2, "foo" ] +{{}} +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "additionalItems": { "type": "string" } +} +{{}} + +{{}} +[ 1, 2, 3 ] +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/additionalProperties.markdown b/content/draft6/validation/additionalProperties.markdown index dda9ea71..a3b9f12b 100644 --- a/content/draft6/validation/additionalProperties.markdown +++ b/content/draft6/validation/additionalProperties.markdown @@ -31,11 +31,11 @@ related: keyword: maxProperties --- -The `additionalProperties` keyword restricts object instance properties not -described by the _sibling_ [`properties`]({{< ref -"draft6/validation/properties" ->}}) and [`patternProperties`]({{< ref "draft6/validation/patternproperties" ->}}) keywords (if any), to validate against the given subschema. +The [`additionalProperties`]({{< ref "draft6/validation/additionalproperties" +>}}) keyword restricts object instance properties not described by the +_sibling_ [`properties`]({{< ref "draft6/validation/properties" >}}) and +[`patternProperties`]({{< ref "draft6/validation/patternproperties" >}}) +keywords (if any), to validate against the given subschema. {{}}The use of the [`properties`]({{< ref "draft6/validation/properties" >}}) keyword **does not prevent the presence of diff --git a/content/draft6/validation/allOf.markdown b/content/draft6/validation/allOf.markdown index 1654d37f..bd30de94 100644 --- a/content/draft6/validation/allOf.markdown +++ b/content/draft6/validation/allOf.markdown @@ -118,10 +118,10 @@ result of this keyword given 3 subschemas: A, B, and C. { "$schema": "http://json-schema.org/draft-06/schema#", "allOf": [ - { "$ref": "#/$defs/foo" }, - { "$ref": "#/$defs/bar" } + { "$ref": "#/definitions/foo" }, + { "$ref": "#/definitions/bar" } ], - "$defs": { + "definitions": { "foo": { "type": "number" }, "bar": { "type": "integer" } } diff --git a/content/draft6/validation/anyOf.markdown b/content/draft6/validation/anyOf.markdown index 19f86458..7adc9095 100644 --- a/content/draft6/validation/anyOf.markdown +++ b/content/draft6/validation/anyOf.markdown @@ -19,3 +19,111 @@ related: - vocabulary: validation keyword: not --- + +The [`anyOf`]({{< ref "draft6/validation/anyof" >}}) keyword restricts +instances to validate against _at least one_ (but potentially multiple) of the +given subschemas. This keyword represents a [logical +disjunction](https://en.wikipedia.org/wiki/Logical_disjunction) (OR) +operation, as instances are valid if they satisfy the constraints of one or +more subschemas (the union of the constraints). + + +This keyword is equivalent to the `||` operator found in most programming +languages. For example: + +```c +bool valid = A || B || C; +``` + +As a reference, the following boolean [truth +table](https://en.wikipedia.org/wiki/Truth_table) considers the evaluation +result of this keyword given 3 subschemas: A, B, and C. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
anyOfSubschema ASubschema BSubschema C
Invalid Invalid Invalid Invalid
Valid Invalid Invalid Valid
Valid Invalid Valid Invalid
Valid Invalid Valid Valid
Valid Valid Invalid Invalid
Valid Valid Invalid Valid
Valid Valid Valid Invalid
Valid Valid Valid Valid
+ +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "anyOf": [ + { "required": [ "foo" ] }, + { "required": [ "bar" ] } + ] +} +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +{ "bar": 2 } +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "extra": 4 } +{{}} diff --git a/content/draft6/validation/const.markdown b/content/draft6/validation/const.markdown index 27e549cf..f883791c 100644 --- a/content/draft6/validation/const.markdown +++ b/content/draft6/validation/const.markdown @@ -17,3 +17,64 @@ related: - vocabulary: validation keyword: type --- + + +The [`const`]({{< ref "draft6/validation/const" >}}) keyword (short for +"constant") restricts instances to a single specific JSON value of any type. + +{{}} Constraining instances to a constant value by definition +implies the given JSON type. Therefore, combining this keyword with the +[`type`]({{< ref "draft6/validation/type" >}}) keyword is redundant (or even +invalid if types don't agree), and considered an +anti-pattern.{{}} + +{{}} There are programming languages, such as JavaScript, that +[cannot distinguish between integers and real +numbers](https://2ality.com/2012/04/number-encoding.html). To accommodate for +those cases, JSON Schema considers a real number with a zero fractional part to +be equal to the corresponding integer. For example, in JSON Schema, `1` is +considered to be equal to `1.0`.{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "const": 5 +} +{{}} + +{{}} +5 +{{}} + +{{}} +5.0 +{{}} + +{{}} +1234 +{{}} + +{{}} +"Hello" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "const": { "name": "John Doe", "age": 30 } +} +{{}} + +{{}} +{ "name": "John Doe", "age": 30 } +{{}} + +{{}} +{ "name": "Jane Doe", "age": 30 } +{{}} + +{{}} +30 +{{}} diff --git a/content/draft6/validation/contains.markdown b/content/draft6/validation/contains.markdown index 9cccf2c4..a95ec2a2 100644 --- a/content/draft6/validation/contains.markdown +++ b/content/draft6/validation/contains.markdown @@ -25,3 +25,46 @@ related: - vocabulary: validation keyword: uniqueItems --- + + +The [`contains`]({{< ref "draft6/validation/contains" >}}) keyword restricts +array instances to include one or more items (at any location of the array) +that validate against the given subschema. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "contains": { + "type": "number", + "multipleOf": 2 + } +} +{{}} + +{{}} +[ "foo", 2, false, [ "bar" ], -5 ] +{{}} + +{{}} +[ "foo", 2, false, 3, 4, [ "bar" ], -5, -3.0 ] +{{}} + +{{}} +[ 2, 4, 6, 8, 10, 12 ] +{{}} + +{{}} +[ "foo", true ] +{{}} + +{{}} +[] +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/default.markdown b/content/draft6/validation/default.markdown index b7c8485d..822efa46 100644 --- a/content/draft6/validation/default.markdown +++ b/content/draft6/validation/default.markdown @@ -19,3 +19,92 @@ related: - vocabulary: validation keyword: examples --- + + +The [`default`]({{< ref "draft6/validation/default" >}}) keyword declares a +default instance value for a schema or any of its subschemas, typically to +support specialised tooling like documentation and form generators. This +keyword is merely descriptive and does not affect validation. + +{{}} + +The standard evaluation process will not automatically use these values to fill +in missing parts of the instance. Furthermore, the JSON Schema specification +does not provide any guidance on how this keyword should be used. + +Consult the documentation of any JSON Schema tooling you rely on to check if +and how it makes use of this keyword. + +{{}} + +{{}} + +Meta-schema validation will not check that the default values you declare are +actually valid against their respective schemas, as JSON Schema does not offer +a mechanism for meta-schemas to declare that instances validate against parts +of the same instance being evaluated. As a consequence, it is not rare for +schemas to declare invalid default values that go undetected for a long time. + +It is recommended to use the [`jsonschema +lint`](https://github.com/sourcemeta/jsonschema/blob/main/docs/lint.markdown) +command, as this linter performs further checks to detect many corner cases, +including this one. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "object", + "default": {}, + "properties": { + "language": { "default": "en" }, + "notifications": { "default": true } + } +} +{{}} + +{{}} +{ "language": "es", "notifications": false } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "email": { + "default": "johndoe@acme.com", + "$ref": "#/definitions/email-address" + } + }, + "definitions": { + "email-address": { + "type": "string", + "format": "email", + "default": "example@example.org" + } + } +} +{{}} + +{{}} +{ "email": "jane@foo.com" } +{{}} + +{{}} +{} +{{}} + +{{}} +{ "email": 1 } +{{}} diff --git a/content/draft6/validation/definitions.markdown b/content/draft6/validation/definitions.markdown index ead43093..8a3a002f 100644 --- a/content/draft6/validation/definitions.markdown +++ b/content/draft6/validation/definitions.markdown @@ -17,3 +17,62 @@ related: - vocabulary: core keyword: $ref --- + + +The [`definitions`]({{< ref "draft6/validation/definitions" >}}) keyword is a +container for storing reusable schemas within a schema resource, which can be +referenced using the [`$ref`]({{< ref "draft6/core/ref" >}}) keyword. From a +software engineering point of view, this keyword is analogous to defining +_internal_ helper functions as part of a larger program. + +{{}} + +Use this keyword to reduce duplication of internal declarations within a +schema. However, **prefer extracting standalone entities that represent more +than just internal helpers into separate schema files**, and externally +referencing them instead. Otherwise, you will end up with big monolithic +schemas that are challenging to understand and maintain. + +If you need to resolve external references in advance (for distribution or +analysis), look at the [`jsonschema +bundle`](https://github.com/sourcemeta/jsonschema/blob/main/docs/bundle.markdown) +command. + +{{}} + +{{}} + +This keyword declares helper schemas for use _within_ the same schema file or +resource. Defining schema files or resources that use this keyword (and +typically no other keyword) to group common definitions for _other_ schema +files or resources to reference is considered to be an anti-pattern. If you +want to share a schema across multiple schema files or resources, that common +schema should be a standalone schema file or resource itself. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "firstName": { "$ref": "#/definitions/nonEmptyString" }, + "lastName": { "$ref": "#/definitions/nonEmptyString" } + }, + "definitions": { + "nonEmptyString": { + "type": "string", + "minLength": 1 + } + } +} +{{}} + +{{}} +{ "firstName": "John", "lastName": "Doe" } +{{}} + +{{}} +{ "firstName": "", "lastName": "" } +{{}} diff --git a/content/draft6/validation/dependencies.markdown b/content/draft6/validation/dependencies.markdown index cda3d7be..1f7c499b 100644 --- a/content/draft6/validation/dependencies.markdown +++ b/content/draft6/validation/dependencies.markdown @@ -19,3 +19,206 @@ related: - vocabulary: validation keyword: required --- + + +The [`dependencies`]({{< ref "draft6/validation/dependencies" >}}) keyword is +used to express property-based constraints on object instances. It has two +different modes of operation depending on the type of each dependency value: + +- **Property Dependencies (Array)**: When a dependency value is set to an array + of strings, [`dependencies`]({{< ref "draft6/validation/dependencies" >}}) + restricts object instances to define certain properties if the corresponding + property key is also defined. + +- **Schema Dependencies (Schema)**: When a dependency value is set to a schema, + [`dependencies`]({{< ref "draft6/validation/dependencies" >}}) restricts + object instances to validate against the given subschema if the corresponding + property key is defined. Note that the given subschema is evaluated against + the object that defines the property dependency. + +{{}} Note that multiple potentially interrelated dependencies +can be declared at once, in which case every dependency must be transitively +fulfilled for the object instance to be valid. For example, if a schema marks +the property `B` as required if the property `A` is present and also marks the +property `C` as required if the property `B` is present, defining the property +`A` transitively requires _both_ the `B` and `C` properties to be present in +the object instance. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "dependencies": { + "foo": [ "bar", "baz" ] + } +} +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +{ "qux": 4 } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "dependencies": { + "foo": [ "bar" ], + "bar": [ "baz" ] + } +} +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "bar": 2, "baz": 3 } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "dependencies": { + "foo": { "maxProperties": 2 } + } +} +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "firstName": "John", "lastName": "Doe", "age": 50 } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "dependencies": { + "foo": { "maxProperties": 2 }, + "bar": { "minProperties": 2 } + } +} +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "foo": 1, "bar": 2, "extra": true } +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +{ "foo": 1, "name": "John Doe", "age": 50 } +{{}} + +{{}} +{ "bar": 2 } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "dependencies": { + "creditCard": [ "billingAddress" ], + "billingAddress": { "required": [ "street", "city", "zipcode" ] } + } +} +{{}} + +{{}} +{ + "creditCard": "1234-5678-9012-3456", + "billingAddress": { + "street": "123 Main St", + "city": "Anytown", + "zipcode": "12345" + } +} +{{}} + +{{}} +{ "creditCard": "1234-5678-9012-3456" } +{{}} + +{{}} +{ + "billingAddress": { + "street": "123 Main St" + } +} +{{}} + +{{}} +{ "name": "John Doe" } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/description.markdown b/content/draft6/validation/description.markdown index 1fdd22dc..ca842052 100644 --- a/content/draft6/validation/description.markdown +++ b/content/draft6/validation/description.markdown @@ -17,3 +17,82 @@ related: - vocabulary: validation keyword: default --- + + +The [`description`]({{< ref "draft6/validation/description" >}}) keyword is a +placeholder for a longer human-readable string summary of what a schema or any +of its subschemas are about. This keyword is merely descriptive and does not +affect validation. + +{{}} + +We heavily recommend to declare this keyword at the top level of every schema, +as a human-readable longer description of what the schema is about. +Note that this keyword is meant to be to be used in conjunction with the +[`title`]({{< ref "draft6/validation/title" >}}) keyword. The idea is to +augment the short summary with a longer description, and not to avoid the +concise summary altogether. + +{{}} + +{{}} + +Tooling makers must be careful when statically traversing schemas in search of +occurrences of this keyword. It is possible for schemas to make use of this +keyword behind conditional operators, references, or any other type of keyword +that makes it hard or even impossible to correctly locate these values in all +cases. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Even Number", + "description": "This schema describes an even number", + "type": "number", + "multipleOf": 2 +} +{{}} + +{{}} +10 +{{}} + +{{}} +7 +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Number", + "type": "number", + "anyOf": [ + { + "description": "This is an even number", + "multipleOf": 2 + }, + { + "description": "This is an odd number", + "not": { + "multipleOf": 2 + } + } + ] +} +{{}} + +{{}} +10 +{{}} + +{{}} +7 +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/enum.markdown b/content/draft6/validation/enum.markdown index 31b82ff3..adf2e89f 100644 --- a/content/draft6/validation/enum.markdown +++ b/content/draft6/validation/enum.markdown @@ -21,3 +21,83 @@ related: - vocabulary: validation keyword: oneOf --- + + +The [`enum`]({{< ref "draft6/validation/enum" >}}) keyword restricts instances +to a finite set of possible values, which may be of different types. + +{{}} Constraining instances to a set of possible values by +definition implies the given JSON types. Therefore, combining this keyword with +the [`type`]({{< ref "draft6/validation/type" >}}) keyword is redundant (or +even invalid if types don't agree), and considered an +anti-pattern.{{}} + +{{}} There are programming languages, such as JavaScript, that +[cannot distinguish between integers and real +numbers](https://2ality.com/2012/04/number-encoding.html). To accommodate for +those cases, JSON Schema considers a real number with a zero fractional part to +be equal to the corresponding integer. For example, in JSON Schema, `1` is +considered to be equal to `1.0`.{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "enum": [ "red", "green", "blue" ] +} +{{}} + +{{}} +"green" +{{}} + +{{}} +"black" +{{}} + +{{}} +2 +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "enum": [ 1, 2.0, 3 ] +} +{{}} + +{{}} +1 +{{}} + +{{}} +2 +{{}} + +{{}} +5 +{{}} + +{{}} +"Hello" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "enum": [ "red", 123, true, { "foo": "bar" }, [ 1, 2 ], null ] +} +{{}} + +{{}} +true +{{}} + +{{}} +{ "foo": "bar" } +{{}} + +{{}} +{ "foo": "baz" } +{{}} diff --git a/content/draft6/validation/examples.markdown b/content/draft6/validation/examples.markdown index b4c6d0db..72c67d2a 100644 --- a/content/draft6/validation/examples.markdown +++ b/content/draft6/validation/examples.markdown @@ -19,3 +19,58 @@ related: - vocabulary: validation keyword: default --- + + + +The [`examples`]({{< ref "draft6/validation/examples" >}}) keyword declares a +set of example instances for a schema or any of its subschemas, typically for +documentation purposes. This keyword is merely descriptive and does not affect +validation. + +{{}} + +Meta-schema validation will not check that the examples you declare are +actually valid against their respective schemas, as JSON Schema does not offer +a mechanism for meta-schemas to declare that instances validate against parts +of the same instance being evaluated. As a consequence, it is not rare for +schemas to declare invalid examples that go undetected for a long time. + +It is recommended to use the [`jsonschema +lint`](https://github.com/sourcemeta/jsonschema/blob/main/docs/lint.markdown) +command, as this linter performs further checks to detect many corner cases, +including this one. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "examples": [ + { "name": "John Doe", "age": 23 } + ], + "properties": { + "name": { + "type": "string", + "examples": [ "John Doe", "Jane Doe" ] + }, + "age": { + "type": "integer", + "examples": [ 1, 18, 55 ] + } + } +} +{{}} + +{{}} +{ "name": "Juan Cruz Viotti", "age": 30 } +{{}} + +{{}} +{ "age": 50 } +{{}} + +{{}} +{ "name": 1, "age": true } +{{}} diff --git a/content/draft6/validation/exclusiveMaximum.markdown b/content/draft6/validation/exclusiveMaximum.markdown index 338c5b69..1134c454 100644 --- a/content/draft6/validation/exclusiveMaximum.markdown +++ b/content/draft6/validation/exclusiveMaximum.markdown @@ -21,3 +21,77 @@ related: - vocabulary: validation keyword: multipleOf --- + + +The [`exclusiveMaximum`]({{< ref "draft6/validation/exclusivemaximum" >}}) keyword restricts number instances to be strictly less +than the given number. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "exclusiveMaximum": 10 +} +{{}} + +{{}} +9.9 +{{}} + +{{}} +9 +{{}} + +{{}} +10.001 +{{}} + +{{}} +11 +{{}} + +{{}} +10.0 +{{}} + +{{}} +10 +{{}} + +{{}} +"100000" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "exclusiveMaximum": -2.1 +} +{{}} + +{{}} +-2.2 +{{}} + +{{}} +-3 +{{}} + +{{}} +-2.01 +{{}} + +{{}} +-2 +{{}} + +{{}} +-2.1 +{{}} + +{{}} +"100000" +{{}} diff --git a/content/draft6/validation/exclusiveMinimum.markdown b/content/draft6/validation/exclusiveMinimum.markdown index 896906a0..d29526ae 100644 --- a/content/draft6/validation/exclusiveMinimum.markdown +++ b/content/draft6/validation/exclusiveMinimum.markdown @@ -21,3 +21,77 @@ related: - vocabulary: validation keyword: multipleOf --- + + +The [`exclusiveMinimum`]({{< ref "draft6/validation/exclusiveminimum" >}}) keyword restricts number instances to be strictly +greater than the given number. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "exclusiveMinimum": 10 +} +{{}} + +{{}} +10.1 +{{}} + +{{}} +11 +{{}} + +{{}} +9.9 +{{}} + +{{}} +9 +{{}} + +{{}} +10.0 +{{}} + +{{}} +10 +{{}} + +{{}} +"100000" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "exclusiveMinimum": -2.1 +} +{{}} + +{{}} +-2.09 +{{}} + +{{}} +-2 +{{}} + +{{}} +-2.11 +{{}} + +{{}} +-3 +{{}} + +{{}} +-2.1 +{{}} + +{{}} +"100000" +{{}} diff --git a/content/draft6/validation/format.markdown b/content/draft6/validation/format.markdown index 3e86f9c8..f785e2ac 100644 --- a/content/draft6/validation/format.markdown +++ b/content/draft6/validation/format.markdown @@ -15,3 +15,72 @@ changed_in: - draft3 - draft4 --- + + +The [`format`]({{< ref "draft6/validation/format" >}}) keyword communicates +that string instances are of the given logical type. + +{{}} By default, this keyword does not perform validation, as +validating formats is considered optional by the official JSON Schema Test +Suite. As a consequence, not many implementations support it. If validation is +desired, the best practice is to combine this keyword with the [`pattern`]({{< ref "draft6/validation/pattern" >}}) keyword. This guarantees interoperable +and unambiguous behavior across JSON Schema implementations. +{{}} + +{{}} While [technically +allowed](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8) +by the JSON Schema specification, extending this keyword with custom formats is +considered to be an anti-pattern that can introduce interoperability issues and +undefined behavior. As a best practice, stick to standardised formats. If +needed, introduce a new keyword for custom string logical +types.{{}} + +{{}} This keyword and its validation guarantees are a common +source of confusion of the JSON Schema specification across versions. + +Since the introduction of this keyword, the JSON Schema specifications +clarified that validation was not mandatory. However, the majority of older +Schema implementations did support validation, leading schema-writers to rely +on it. At the same time, a second problem emerged: implementations often didn't +agree on the strictness of validation, mainly on complex logical types like +e-mail addresses, leading to various interoperability issues. + +To avoid the gray areas of this keyword, we recommend only treating it as +semantic metadata, never enabling validation support at the implementation +level (even if supported), and performing validation using the [`pattern`]({{< +ref "draft6/validation/pattern" >}}) keyword. {{}} + +The supported formats are the following. + +| Format | Category | Specification | +|-------------------|----------------------|---------------| +| `"date-time"` | Time | [JSON Schema Draft 6 Validation Section 8.3.1](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.1) | +| `"email"` | Emails | [JSON Schema Draft 6 Validation Section 8.3.2](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.2) | +| `"hostname"` | Hostnames | [JSON Schema Draft 6 Validation Section 8.3.3](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.3) | +| `"ipv4"` | IP Addresses | [JSON Schema Draft 6 Validation Section 8.3.4](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.4) | +| `"ipv6"` | IP Addresses | [JSON Schema Draft 6 Validation Section 8.3.5](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.5) | +| `"uri"` | Resource Identifiers | [JSON Schema Draft 6 Validation Section 8.3.6](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.6) | +| `"uri-reference"` | Resource Identifiers | [JSON Schema Draft 6 Validation Section 8.3.7](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.7) | +| `"uri-template"` | Resource Identifiers | [JSON Schema Draft 6 Validation Section 8.3.8](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.8) | +| `"json-pointer"` | JSON Pointer | [JSON Schema Draft 6 Validation Section 8.3.9](https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.8.3.9) | + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "format": "email" +} +{{}} + +{{}} +"john.doe@example.com" +{{}} + +{{}} +"foo-bar" +{{}} + +{{}} +45 +{{}} diff --git a/content/draft6/validation/items.markdown b/content/draft6/validation/items.markdown index 33d7d0c3..a15588ac 100644 --- a/content/draft6/validation/items.markdown +++ b/content/draft6/validation/items.markdown @@ -31,3 +31,108 @@ related: - vocabulary: validation keyword: uniqueItems --- + + +The [`items`]({{< ref "draft6/validation/items" >}}) keyword is used to +validate array items and has two different modes of operation depending on the +type of its value: + +- **Schema**: When set to a schema, [`items`]({{< ref "draft6/validation/items" + >}}) validates that all items in the array instance validate against the + given subschema. + +- **Array**: When set to an array of schemas, [`items`]({{< ref + "draft6/validation/items" >}}) validates each item in the array instance + against the subschema at the corresponding position. Items beyond the length + of the [`items`]({{< ref "draft6/validation/items" >}}) array can be + validated using the [`additionalItems`]({{< ref + "draft6/validation/additionalitems" >}}) keyword. + +{{}}This keyword does not prevent an array instance from being +empty. If needed, use the [`minItems`]({{< ref "draft6/validation/minitems" >}}) to assert on the minimum bounds of the array.{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": { "type": "number" } +} +{{}} + +{{}} +[ 1, -3.4, 54 ] +{{}} + +{{}} +[] +{{}} + +{{}} +[ 1, -3.4, 54, "foo" ] +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": [ { "type": "boolean" }, { "type": "number" } ] +} +{{}} + +{{}} +[ false, 35 ] +{{}} + +{{}} +[ false, 35, "foo", "bar" ] +{{}} + +{{}} +[ "not a boolean", 35 ] +{{}} + +{{}} +[ false, "not a number" ] +{{}} + +{{}} +[] +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": [ { "type": "boolean" }, { "type": "number" } ], + "additionalItems": { "type": "string" } +} +{{}} + +{{}} +[ false, 35 ] +{{}} + +{{}} +[ false, 35, "foo", "bar" ] +{{}} + +{{}} +[ false, 35, { "foo": "bar" } ] +{{}} + +{{}} +[] +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/maxItems.markdown b/content/draft6/validation/maxItems.markdown index d6338a99..4c9e199c 100644 --- a/content/draft6/validation/maxItems.markdown +++ b/content/draft6/validation/maxItems.markdown @@ -21,3 +21,42 @@ related: - vocabulary: validation keyword: contains --- + + +The [`maxItems`]({{< ref "draft6/validation/maxitems" >}}) keyword restricts array instances to consists of an inclusive +maximum numbers of items. + +{{}} The presence of this keyword does not depend on the +presence of the [`items`]({{< ref "draft6/validation/items" >}}) keyword. +{{}} + +{{}}To restrict array instances to the empty array, prefer using +the [`const`]({{< ref "draft6/validation/const" >}}) keyword instead of +setting this keyword to `0`. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "maxItems": 3 +} +{{}} + +{{}} +[ 1, 2, 3, 4 ] +{{}} + +{{}} +[ 1, true, "hello" ] +{{}} + +{{}} +[ false, "foo" ] +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/maxLength.markdown b/content/draft6/validation/maxLength.markdown index 0369b97a..93942cdd 100644 --- a/content/draft6/validation/maxLength.markdown +++ b/content/draft6/validation/maxLength.markdown @@ -19,3 +19,57 @@ related: - vocabulary: validation keyword: format --- + + +The [`maxLength`]({{< ref "draft6/validation/maxlength" >}}) keyword restricts string instances to consists of an inclusive +maximum number of [Unicode](https://unicode.org) code-points (logical +characters), which is not necessarily the same as the number of bytes in the +string. + +{{}} While the [IETF RFC +8259](https://www.rfc-editor.org/rfc/rfc8259) JSON standard recommends the use +of [UTF-8](https://en.wikipedia.org/wiki/UTF-8), other Unicode encodings are +permitted. Therefore a JSON string may be represented in up to 4x the number of +bytes as its number of code-points (assuming +[UTF-32](https://en.wikipedia.org/wiki/UTF-32) as the upper bound). + +JSON Schema does not provide a mechanism to assert on the byte size of a JSON +string, as this is an implementation-dependent property of the JSON parser in +use. {{}} + +{{}} Be careful when making use of this keyword to +inadvertently assert on the byte length of JSON strings before inserting them +into byte-sensitive destinations like fixed-size buffers. Always assume that +the byte length of a JSON string can arbitrary larger that the number of +logical characters.{{}} + +{{}}To restrict string instances to the empty string, prefer +using the [`const`]({{< ref "draft6/validation/const" >}}) keyword instead of +setting this keyword to `0`. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "maxLength": 3 +} +{{}} + +{{}} +"foo" +{{}} + +{{}} +"こんにちは" +{{}} + +{{}} +"hi" +{{}} + +{{}} +55 +{{}} diff --git a/content/draft6/validation/maxProperties.markdown b/content/draft6/validation/maxProperties.markdown index 6a777d0b..51df3c4e 100644 --- a/content/draft6/validation/maxProperties.markdown +++ b/content/draft6/validation/maxProperties.markdown @@ -21,3 +21,42 @@ related: - vocabulary: validation keyword: additionalProperties --- + + +The [`maxProperties`]({{< ref "draft6/validation/maxproperties" >}}) keyword restricts object instances to consists of an +inclusive maximum numbers of properties. + +{{}} The presence of this keyword does not depend on the +presence of the [`properties`]({{< ref "draft6/validation/properties" >}}) +keyword. {{}} + +{{}}To restrict object instances to the empty object, prefer +using the [`const`]({{< ref "draft6/validation/const" >}}) keyword instead of +setting this keyword to `0`. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "maxProperties": 2 +} +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/maximum.markdown b/content/draft6/validation/maximum.markdown index 7526d871..433fe4bc 100644 --- a/content/draft6/validation/maximum.markdown +++ b/content/draft6/validation/maximum.markdown @@ -21,3 +21,77 @@ related: - vocabulary: validation keyword: multipleOf --- + + +The [`maximum`]({{< ref "draft6/validation/maximum" >}}) keyword restricts number instances to be less than or equal to +the given number. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "maximum": 10 +} +{{}} + +{{}} +9.9 +{{}} + +{{}} +9 +{{}} + +{{}} +10.001 +{{}} + +{{}} +11 +{{}} + +{{}} +10.0 +{{}} + +{{}} +10 +{{}} + +{{}} +"100000" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "maximum": -2.1 +} +{{}} + +{{}} +-2.2 +{{}} + +{{}} +-3 +{{}} + +{{}} +-2.01 +{{}} + +{{}} +-2 +{{}} + +{{}} +-2.1 +{{}} + +{{}} +"100000" +{{}} diff --git a/content/draft6/validation/minItems.markdown b/content/draft6/validation/minItems.markdown index ff17b7e8..091ee13a 100644 --- a/content/draft6/validation/minItems.markdown +++ b/content/draft6/validation/minItems.markdown @@ -23,3 +23,38 @@ related: - vocabulary: validation keyword: contains --- + + +The [`minItems`]({{< ref "draft6/validation/minitems" >}}) keyword restricts array instances to consists of an inclusive +minimum numbers of items. + +{{}} The presence of this keyword does not depend on the +presence of the [`items`]({{< ref "draft6/validation/items" >}}) keyword. +{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "minItems": 3 +} +{{}} + +{{}} +[ 1, 2, 3, 4 ] +{{}} + +{{}} +[ 1, true, "hello" ] +{{}} + +{{}} +[ false, "foo" ] +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/minLength.markdown b/content/draft6/validation/minLength.markdown index 30712fb3..de1673c5 100644 --- a/content/draft6/validation/minLength.markdown +++ b/content/draft6/validation/minLength.markdown @@ -21,3 +21,46 @@ related: - vocabulary: validation keyword: format --- + + +The [`minLength`]({{< ref "draft6/validation/minlength" >}}) keyword restricts string instances to consists of an inclusive +minimum number of [Unicode](https://unicode.org) code-points (logical +characters), which is not necessarily the same as the number of bytes in the +string. + +{{}} While the [IETF RFC +8259](https://www.rfc-editor.org/rfc/rfc8259) JSON standard recommends the use +of [UTF-8](https://en.wikipedia.org/wiki/UTF-8), other Unicode encodings are +permitted. Therefore a JSON string may be represented in more bytes than its +number of code-points. + +JSON Schema does not provide a mechanism to assert on the byte size of a JSON +string, as this is an implementation-dependent property of the JSON parser in +use. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "minLength": 3 +} +{{}} + +{{}} +"foo" +{{}} + +{{}} +"こんにちは" +{{}} + +{{}} +"hi" +{{}} + +{{}} +55 +{{}} diff --git a/content/draft6/validation/minProperties.markdown b/content/draft6/validation/minProperties.markdown index 2323be74..6168d488 100644 --- a/content/draft6/validation/minProperties.markdown +++ b/content/draft6/validation/minProperties.markdown @@ -23,3 +23,38 @@ related: - vocabulary: validation keyword: additionalProperties --- + + +The [`minProperties`]({{< ref "draft6/validation/minproperties" >}}) keyword restricts object instances to consists of an +inclusive minimum numbers of properties. + +{{}} The presence of this keyword does not depend on the +presence of the [`properties`]({{< ref "draft6/validation/properties" >}}) +keyword. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "minProperties": 2 +} +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/minimum.markdown b/content/draft6/validation/minimum.markdown index 68cf1267..a27c8759 100644 --- a/content/draft6/validation/minimum.markdown +++ b/content/draft6/validation/minimum.markdown @@ -21,3 +21,77 @@ related: - vocabulary: validation keyword: multipleOf --- + + +The [`minimum`]({{< ref "draft6/validation/minimum" >}}) keyword restricts number instances to be greater than or equal to +the given number. + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "minimum": 10 +} +{{}} + +{{}} +10.1 +{{}} + +{{}} +11 +{{}} + +{{}} +9.9 +{{}} + +{{}} +9 +{{}} + +{{}} +10.0 +{{}} + +{{}} +10 +{{}} + +{{}} +"100000" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "minimum": -2.1 +} +{{}} + +{{}} +-2.09 +{{}} + +{{}} +-2 +{{}} + +{{}} +-2.11 +{{}} + +{{}} +-3 +{{}} + +{{}} +-2.1 +{{}} + +{{}} +"100000" +{{}} diff --git a/content/draft6/validation/multipleOf.markdown b/content/draft6/validation/multipleOf.markdown index 02bcd42a..641d2012 100644 --- a/content/draft6/validation/multipleOf.markdown +++ b/content/draft6/validation/multipleOf.markdown @@ -23,3 +23,111 @@ related: - vocabulary: validation keyword: minimum --- + + +The [`multipleOf`]({{< ref "draft6/validation/multipleof" >}}) keyword +restricts number instances to be multiples of the given number. Note that the +number `0` is a multiple of every number, as for every number `k`, the +multiplication `0 * k` yield an integer value (in this case always 0). This case +is not to be confused with [division by +zero](https://en.wikipedia.org/wiki/Division_by_zero), which is not a permitted +operation in most computer systems. + +{{}}Setting this keyword to negative powers of 10, such as +`0.01` (10^-2), `0.001` (10^-3), and `0.0001` (10^-4), is a common mechanism to +control the maximum number of digits in the fractional part of a real number. +For example, `1.2` and `-12.34` are multiples of `0.01`, but `1.234` is +not.{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "multipleOf": 5 +} +{{}} + +{{}} +10 +{{}} + +{{}} +-5 +{{}} + +{{}} +15.0 +{{}} + +{{}} +8 +{{}} + +{{}} +0 +{{}} + +{{}} +"100000" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "multipleOf": 2.3 +} +{{}} + +{{}} +6.9 +{{}} + +{{}} +-4.6 +{{}} + +{{}} +2.4 +{{}} + +{{}} +0 +{{}} + +{{}} +"100000" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "multipleOf": 0.01 +} +{{}} + +{{}} +2 +{{}} + +{{}} +5.1 +{{}} + +{{}} +-12.34 +{{}} + +{{}} +1.234 +{{}} + +{{}} +0 +{{}} + +{{}} +"100000" +{{}} diff --git a/content/draft6/validation/not.markdown b/content/draft6/validation/not.markdown index 7639017c..261cd3ac 100644 --- a/content/draft6/validation/not.markdown +++ b/content/draft6/validation/not.markdown @@ -21,3 +21,59 @@ related: - vocabulary: validation keyword: oneOf --- + + +The [`not`]({{< ref "draft6/validation/not" >}}) keyword restricts +instances to fail validation against the given subschema. This keyword +represents a [logical negation](https://en.wikipedia.org/wiki/Negation) (NOT) +operation. In other words, the instance successfully validates against the +schema only if it does not match the given subschema. + + +{{}} Avoid the use of this keyword (usually negating the +[`required`]({{< ref "draft6/validation/required" >}}) keyword) to prohibit +specific object properties from being defined. Instead, use the +[`properties`]({{< ref "draft6/validation/properties" >}}) keyword and set +the disallowed object properties to the `false` boolean +schema.{{}} + +This keyword is equivalent to the `!` operator found in most programming +languages. For example: + +```c +bool valid = !not_schema; +``` + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "not": { + "const": "Prohibited" + } +} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +"Prohibited" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "not": { + "type": "string", + "minLength": 10, + "maxLength": 9 + } +} +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/oneOf.markdown b/content/draft6/validation/oneOf.markdown index e2a4204e..c104c5d1 100644 --- a/content/draft6/validation/oneOf.markdown +++ b/content/draft6/validation/oneOf.markdown @@ -19,3 +19,129 @@ related: - vocabulary: validation keyword: not --- + + +The [`oneOf`]({{< ref "draft6/validation/oneof" >}}) keyword restricts +instances to validate against _exactly one_ (and only one) of the given +subschemas and fail on the rest. This keyword represents a [logical exclusive +disjunction](https://en.wikipedia.org/wiki/Exclusive_or) (XOR) operation. In +practice, the vast majority of schemas don't require exclusive disjunction +semantics but a simple disjunction. If you are not sure, the [`anyOf`]({{< ref +"draft6/validation/anyof" >}}) keyword is probably a better fit. + +{{}} + +Avoid this keyword unless you absolutely need exclusive disjunction +semantics, which is rarely the case. As its name implies, this keyword +enforces the instance to be valid against **only one of its subschemas**. +Therefore, a JSON Schema implementation will exhaustively evaluate every +subschema to make sure the rest fails, potentially introducing unnecessary +computational overhead. + +{{}} + +This keyword is equivalent to the following complex boolean construct that +combines the `||`, `&&`, and `!` operators found in most programming +languages: + +```c +bool valid = (A && !B && !C) || (!A && B && !C) || (!A && !B && C); +``` + +As a reference, the following boolean [truth +table](https://en.wikipedia.org/wiki/Truth_table) considers the evaluation +result of this keyword given 3 subschemas: A, B, and C. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
oneOfSubschema ASubschema BSubschema C
Invalid Invalid Invalid Invalid
Valid Invalid Invalid Valid
Valid Invalid Valid Invalid
Invalid Invalid Valid Valid
Valid Valid Invalid Invalid
Invalid Valid Invalid Valid
Invalid Valid Valid Invalid
Invalid Valid Valid Valid
+ +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "oneOf": [ + { "required": [ "foo" ] }, + { "required": [ "bar" ] }, + { "required": [ "baz" ] } + ] +} +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +{ "bar": 2 } +{{}} + +{{}} +{ "foo": 1, "bar": 2 } +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "extra": 4 } +{{}} diff --git a/content/draft6/validation/pattern.markdown b/content/draft6/validation/pattern.markdown index fbb06d7d..554bf63d 100644 --- a/content/draft6/validation/pattern.markdown +++ b/content/draft6/validation/pattern.markdown @@ -23,3 +23,55 @@ related: - vocabulary: validation keyword: patternProperties --- + + +The [`pattern`]({{< ref "draft6/validation/pattern" >}}) keyword restricts +string instances to match the given regular expression. + +{{}} While the specification suggests the use of +[ECMA-262](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/) +regular expressions for interoperability purposes, the use of different +flavours like PCRE or POSIX (Basic or Extended) is permitted. Also, the +specification does not impose the use of any particular regular expression +flag. By convention (and somewhat enforced by the official JSON Schema test +suite), regular expressions are not implicitly +[anchored](https://www.regular-expressions.info/anchors.html) and are always +treated as case-sensitive. It is also common for the +[`DOTALL`](https://tc39.es/ecma262/multipage/text-processing.html#sec-get-regexp.prototype.dotAll) +flag to be enabled, permitting the dot character class to match new lines. + +To avoid interoperability issues, stick to +[ECMA-262](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/), +and don't assume the use of any regular expression flag. {{}} + +{{}} Regular expressions often make use of characters that need +to be escaped when making use of them as part of JSON strings. For example, the +*reverse solidus* character (more commonly known as the backslash character) +and the *double quote* character need to be escaped. Failure to do so will +result in an invalid JSON document. Applications to work with regular +expressions, like [Regex Forge](https://regexforge.com), typically provide +convenient functionality to copy a regular expression for use in JSON. +{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" +} +{{}} + +{{}} +"john.doe@example.com" +{{}} + +{{}} +"foo" +{{}} + +{{}} +1234 +{{}} diff --git a/content/draft6/validation/patternProperties.markdown b/content/draft6/validation/patternProperties.markdown index 4f671573..cb13054f 100644 --- a/content/draft6/validation/patternProperties.markdown +++ b/content/draft6/validation/patternProperties.markdown @@ -32,3 +32,136 @@ related: - vocabulary: validation keyword: maxProperties --- + + +The [`patternProperties`]({{< ref "draft6/validation/patternproperties" >}}) +keyword restricts properties of an object instance that match certain regular +expressions to match their corresponding subschemas definitions. + +{{}} This keyword is evaluated independently of the +[`properties`]({{< ref "draft6/validation/properties" >}}) keyword. If an +object property is described by both keywords, then both subschemas must +successfully validate against the given property for validation to succeed. +Furthermore, an instance property may match more than one regular expression +set with this keyword, in which case the property is expected to validate +against all matching subschemas.{{}} + +{{}} While the specification suggests the use of +[ECMA-262](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/) +regular expressions for interoperability purposes, the use of different +flavours like PCRE or POSIX (Basic or Extended) is permitted. Also, the +specification does not impose the use of any particular regular expression +flag. By convention (and somewhat enforced by the official JSON Schema test +suite), regular expressions are not implicitly +[anchored](https://www.regular-expressions.info/anchors.html) and are always +treated as case-sensitive. It is also common for the +[`DOTALL`](https://tc39.es/ecma262/multipage/text-processing.html#sec-get-regexp.prototype.dotAll) +flag to be enabled, permitting the dot character class to match new lines. + +To avoid interoperability issues, stick to +[ECMA-262](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/), +and don't assume the use of any regular expression flag. {{}} + +{{}} Regular expressions often make use of characters that need +to be escaped when making use of them as part of JSON strings. For example, the +*reverse solidus* character (more commonly known as the backslash character) +and the *double quote* character need to be escaped. Failure to do so will +result in an invalid JSON document. Applications to work with regular +expressions, like [Regex Forge](https://regexforge.com), typically provide +convenient functionality to copy a regular expression for use in JSON. +{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "patternProperties": { + "^[a-z]+$": { "type": "integer" } + } +} +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "CamelCase": true, "alphanumeric123": "anything is valid" } +{{}} + +{{}} +{} +{{}} + +{{}} +{ "foo": "should have been an integer" } +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "patternProperties": { + "^f": { "type": "string" }, + "o$": { "minLength": 3 } + } +} +{{}} + +{{}} +{ "foo": "long string" } +{{}} + +{{}} +{ "boo": 1 } +{{}} + +{{}} +{ "foo": "xx" } +{{}} + +{{}} +{ "boo": "xx" } +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "patternProperties": { + "^f": { "minLength": 3 } + }, + "properties": { + "foo": { "type": "string" } + } +} +{{}} + +{{}} +{ "foo": "long string" } +{{}} + +{{}} +{ "football": 3 } +{{}} + +{{}} +{ "foo": "xx" } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/properties.markdown b/content/draft6/validation/properties.markdown index 8db28d64..112db992 100644 --- a/content/draft6/validation/properties.markdown +++ b/content/draft6/validation/properties.markdown @@ -30,3 +30,100 @@ related: - vocabulary: validation keyword: maxProperties --- + + +The [`properties`]({{< ref "draft6/validation/properties" >}}) keyword +restricts properties of an object instance, when present, to match their +corresponding subschemas definitions. + +{{}}The use of this keyword **does not prevent the presence of +other properties** in the object instance and **does not enforce the presence +of the declared properties**. In other words, additional data that is not +explicitly prohibited is permitted by default. This is intended behaviour to +ease schema evolution (open schemas are backwards compatible by default) and to +enable highly-expressive constraint-driven schemas. + +If you want to restrict instances to only contain the properties you declared, +you must set the [`additionalProperties`]({{< ref "draft6/validation/additionalproperties" >}}) keyword to the boolean schema +`false`, and if you want to enforce the presence of certain properties, you +must use the [`required`]({{< ref "draft6/validation/required" >}}) keyword +accordingly. {{}} + +{{}}Setting properties defined by this keyword to the boolean +schema `false` is an common trick to express that such properties are +forbidden. This is considered more elegant (and usually more performant) than +using the [`not`]({{< ref "draft6/validation/not" >}}) applicator to negate +the [`required`]({{< ref "draft6/validation/required" >}}) keyword. However, +setting properties defined by this keyword to the boolean `true` is considered +to be redundant and an anti-pattern, as additional properties are permitted by +default. {{}} + +{{}} This keyword is evaluated independently of the +[`patternProperties`]({{< ref "draft6/validation/patternproperties" >}}) +keyword. If an object property is described by both keywords, then both schemas +must successfully validate against the given property for validation to +succeed. {{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "name": { "type": "string" }, + "age": { "type": "integer" } + } +} +{{}} + +{{}} +{ "name": "John Doe", "age": 50 } +{{}} + +{{}} +{ "name": "John Doe" } +{{}} + +{{}} +{} +{{}} + +{{}} +{ "name": "John Doe", "age": "this should have been an integer" } +{{}} + +{{}} +{ "name": 999 } +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "forbidden": false, + "permitted": true + } +} +{{}} + +{{}} +{ "permitted": "anything is valid" } +{{}} + +{{}} +{ "foo": "bar", "baz": 2 } +{{}} + +{{}} +{ "forbidden": 1 } +{{}} + +{{}} +{ "forbidden": 1, "permitted": 2 } +{{}} diff --git a/content/draft6/validation/propertyNames.markdown b/content/draft6/validation/propertyNames.markdown index df5f0fb5..3e0a0f42 100644 --- a/content/draft6/validation/propertyNames.markdown +++ b/content/draft6/validation/propertyNames.markdown @@ -27,3 +27,95 @@ related: - vocabulary: validation keyword: maxProperties --- + + +The [`propertyNames`]({{< ref "draft6/validation/propertynames" >}}) keyword +restricts object instances to only define properties whose names match the given +schema. This keyword is evaluated against _every_ property of the object +instance, independently of keywords that indirectly introduce property names +such as [`properties`]({{< ref "draft6/validation/properties" >}}) and +[`patternProperties`]({{< ref "draft6/validation/patternproperties" >}}). + +{{}} As per the JSON grammar, the name of an object property +must be a string. Therefore, setting this keyword to a schema that makes use +of keywords that only apply to types other than strings (such as the +[`properties`]({{< ref "draft6/validation/properties" >}}) keyword) is +either meaningless or leads to unsatisfiable schemas. Conversely, explicitly +setting the [`type`]({{< ref "draft6/validation/type" >}}) keyword to +`string` is redundant. {{}} + +{{}} This keyword is useful when describing JSON objects whose +properties cannot be known in advance. For example, allowing extensions that +must adhere to a certain name convention. If that's not the case, prefer +explicitly listing every permitted property using the [`properties`]({{< ref "draft6/validation/properties" >}}) or [`patternProperties`]({{< ref "draft6/validation/patternproperties" >}}) keywords, and potentially closing +the object by setting the [`additionalProperties`]({{< ref "draft6/validation/additionalproperties" >}}) keyword to `false`. +{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "propertyNames": { "pattern": "^[a-z]*$" } +} +{{}} + +{{}} +{ "foo": "bar" } +{{}} + +{{}} +{} +{{}} + +{{}} +{ "CamelCase": true, "alphanumeric123": false } +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "propertyNames": { "type": "array" } +} +{{}} + +{{}} +{ "foo": "bar" } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "propertyNames": { "pattern": "^b" }, + "properties": { + "foo": { "type": "integer" }, + "bar": { "type": "integer" } + } +} +{{}} + +{{}} +{ "foo": 1 } +{{}} + +{{}} +{ "bar": "should have been an integer" } +{{}} + +{{}} +{ "baz": "qux" } +{{}} diff --git a/content/draft6/validation/required.markdown b/content/draft6/validation/required.markdown index 2dade768..6c0bb20f 100644 --- a/content/draft6/validation/required.markdown +++ b/content/draft6/validation/required.markdown @@ -23,3 +23,80 @@ related: - vocabulary: validation keyword: minProperties --- + + +The [`required`]({{< ref "draft6/validation/required" >}}) keyword restricts +object instances to define the given set of properties. + +{{}} The presence of this keyword does not depend on the +presence of the [`properties`]({{< ref "draft6/validation/properties" >}}) +keyword. The [`required`]({{< ref "draft6/validation/required" >}}) keyword +mandates that certain properties are present (independently of their value), +while the [`properties`]({{< ref "draft6/validation/properties" >}}) keyword +describes the value of such properties when present.{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "required": [ "foo", "bar", "baz" ] +} +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3 } +{{}} + +{{}} +{ "foo": 1, "bar": 2, "baz": 3, "extra": true } +{{}} + +{{}} +{ "foo": 1, "bar": 2, "extra": true } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "required": [ "name", "age" ], + "properties": { + "name": { "type": "string" }, + "age": { "type": "integer" } + } +} +{{}} + +{{}} +{ "name": "John Doe", "age": 30 } +{{}} + +{{}} +{ "name": "John Doe", "age": 30, "extra": true } +{{}} + +{{}} +{ "name": "John Doe" } +{{}} + +{{}} +{ "name": 123, "age": "foo" } +{{}} + +{{}} +{} +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/title.markdown b/content/draft6/validation/title.markdown index 5f1f62cd..0fca191f 100644 --- a/content/draft6/validation/title.markdown +++ b/content/draft6/validation/title.markdown @@ -17,3 +17,76 @@ related: - vocabulary: validation keyword: default --- + + +The [`title`]({{< ref "draft6/validation/title" >}}) keyword is a placeholder +for a concise human-readable string summary of what a schema or any of its +subschemas are about. This keyword is merely descriptive and does not affect +validation. + +{{}} + +We heavily recommend to declare this keyword at the top level of every schema, +as a human-readable introduction to what the schema is about. + +When doing so, note that the JSON Schema specification does not impose or +recommend a maximum length for this keyword. However, it is common practice to +stick to [Git commit message +title](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) +conventions and set it to a capitalised string of *50 characters or less*. If +you run out of space, you can move the additional information to the +[`description`]({{< ref "draft6/validation/description" >}}) keyword. + +{{}} + + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Even Number", + "type": "number", + "multipleOf": 2 +} +{{}} + +{{}} +10 +{{}} + +{{}} +7 +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Number", + "type": "number", + "anyOf": [ + { + "title": "Even Number", + "multipleOf": 2 + }, + { + "title": "Odd Number", + "not": { + "multipleOf": 2 + } + } + ] +} +{{}} + +{{}} +10 +{{}} + +{{}} +7 +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft6/validation/type.markdown b/content/draft6/validation/type.markdown index f12ca266..b2fd4a49 100644 --- a/content/draft6/validation/type.markdown +++ b/content/draft6/validation/type.markdown @@ -16,3 +16,121 @@ introduced_in: draft1 changed_in: - draft4 --- + + +The supported types are the following. Note that while the [ECMA +404](https://ecma-international.org/publications-and-standards/standards/ecma-404/) +JSON standard defines the JSON grammar without mention of encodings, the [IETF +RFC 8259](https://www.rfc-editor.org/rfc/rfc8259) JSON standard provides +specific guidance for JSON numbers and JSON strings which are documented in the +*Interoperable Encoding* column. Other encodings will likely not be accepted by +JSON parsers. + +| Type | Description | Interoperable Encoding | +|-------------|------------------------------------------|----------------------------------------------------------------------------------------------------------| +| `"null"` | The JSON null constant | N/A | +| `"boolean"` | The JSON true or false constants | N/A | +| `"object"` | A JSON object | N/A | +| `"array"` | A JSON array | N/A | +| `"number"` | A JSON number | [IEEE 764](https://ieeexplore.ieee.org/document/8766229) 64-bit double-precision floating point encoding (except `NaN`, `Infinity`, and `+0`) | +| `"integer"` | A JSON number that represents an integer | 64-bit signed integer encoding (from `-(2^53)+1` to `(2^53)-1`) | +| `"string"` | A JSON string | [UTF-8](https://en.wikipedia.org/wiki/UTF-8) Unicode encoding | + +Note that while the JSON grammar does not distinguish between integer and real +numbers, JSON Schema provides the [`integer`]({{< ref "draft6/validation/type" >}}) logical type that matches either integers (such +as `2`), or real numbers where the fractional part is zero (such as `2.0`). +Additionally, numeric constructs inherent to floating point encodings (like +`NaN` and `Infinity`) are not permitted in JSON. However, the negative zero +(`-0`) is permitted. + +{{}} To avoid interoperability issues, do not produce JSON +documents with numbers that exceed the [IETF RFC +8259](https://www.rfc-editor.org/rfc/rfc8259) limits described in the +*Interoperable Encodings* column of the table above. + +If more numeric precision is required, consider representing numbers as JSON +strings or as multiple numbers. For example, fixed-precision real numbers can +be represented as an array of two integers for the integral and fractional +components.{{}} + +{{}} The JavaScript programming language (and by extension +languages such as TypeScript) represent all numbers, including integers, using +the [IEEE 764](https://ieeexplore.ieee.org/document/8766229) floating-point +encoding. As a result, parsing JSON documents with integers beyond the 53-bit +range is prone to precision problems. Read [How numbers are encoded in +JavaScript](https://2ality.com/2012/04/number-encoding.html) by Dr. Axel +Rauschmayer for a more detailed overview of JavaScript's numeric +limitations.{{}} + +{{}}JSON allows numbers to be represented in [scientific +exponential +notation](https://en.wikipedia.org/wiki/Scientific_notation#E_notation). For +example, numbers like `1.0e+28` (equivalent to 10000000000000000000000000000.0) +are valid according to the JSON grammar. This notation is convenient for +expressing long numbers. However, be careful with not accidentally exceeding +the interoperable limits described by the [IETF RFC +8259](https://www.rfc-editor.org/rfc/rfc8259) JSON +standard.{{}} + +## Examples + +{{< schema "A schema that describes numeric instances" >}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "number" +} +{{< /schema >}} + +{{< instance-pass "An integer is valid" >}} +42 +{{< /instance-pass >}} + +{{< instance-pass "A real number is valid" >}} +3.14 +{{< /instance-pass >}} + +{{< instance-pass "A number in scientific exponential notation is valid" >}} +1.0e+28 +{{< /instance-pass >}} + +{{< instance-fail "A string is not valid" >}} +"foo" +{{< /instance-fail >}} + +{{< schema "A schema that describes boolean or array instances" >}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": [ "boolean", "array" ] +} +{{< /schema >}} + +{{< instance-pass "The true boolean is valid" >}} +true +{{< /instance-pass >}} + +{{< instance-fail "A number is invalid" >}} +1234 +{{< /instance-fail >}} + +{{< instance-pass "An arbitrary array is valid" >}} +[ 1, 2, 3 ] +{{< /instance-pass >}} + +{{< schema "A schema that describes integer instances" >}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "type": "integer" +} +{{< /schema >}} + +{{< instance-pass "An integer is valid" >}} +42 +{{< /instance-pass >}} + +{{< instance-pass "A real number with a zero fractional part is valid" >}} +3.0 +{{< /instance-pass >}} + +{{< instance-fail "A real number with a non-zero fractional part is invalid" >}} +3.14 +{{< /instance-fail >}} diff --git a/content/draft6/validation/uniqueItems.markdown b/content/draft6/validation/uniqueItems.markdown index 81e165b0..968ad1e2 100644 --- a/content/draft6/validation/uniqueItems.markdown +++ b/content/draft6/validation/uniqueItems.markdown @@ -21,3 +21,65 @@ related: - vocabulary: validation keyword: contains --- + + +When set to `true`, the [`uniqueItems`]({{< ref "draft6/validation/uniqueitems" >}}) keyword restricts array instances to +items that only occur once in the array. Note that empty arrays and arrays that +consist of a single item satisfy uniqueness by definition. + +{{}} Keep in mind that depending on the size and complexity of +arrays, this keyword may introduce significant validation overhead. The paper +[JSON: data model, query languages and schema +specification](https://arxiv.org/abs/1701.02221) also noted how the presence of +this keyword can negatively impact satisfiability analysis of +schemas.{{}} + +{{}} + +## Examples + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "uniqueItems": true +} +{{}} + +{{}} +[ 1, "hello", true, { "name": "John" } ] +{{}} + +{{}} +[ { "name": "John" }, 1, "hello", true, { "name": "John" } ] +{{}} + +{{}} +[] +{{}} + +{{}} +"Hello World" +{{}} + +{{}} +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "uniqueItems": false +} +{{}} + +{{}} +[ 1, "hello", true, { "name": "John" } ] +{{}} + +{{}} +[ { "name": "John" }, 1, "hello", true, { "name": "John" } ] +{{}} + +{{}} +[] +{{}} + +{{}} +"Hello World" +{{}} diff --git a/content/draft7/validation/format.markdown b/content/draft7/validation/format.markdown index d0c7716a..dbcb44a9 100644 --- a/content/draft7/validation/format.markdown +++ b/content/draft7/validation/format.markdown @@ -17,8 +17,8 @@ changed_in: - draft6 --- -The `format` keyword communicates that string instances are of the given -logical type. +The [`format`]({{< ref "draft7/validation/format" >}}) keyword communicates +that string instances are of the given logical type. {{}} By default, this keyword does not perform validation, as validating formats is considered optional by the official JSON Schema Test