JSON Working Group U. Carion Internet-Draft June 06, 2019 Intended status: Standards Track Expires: December 8, 2019 JSON Schema Language draft-json-schema-language-01 Abstract JavaScript Object Notation (JSON) Schema Language is a portable method for describing the format of JSON ([RFC8259], JavaScript Object Notation) data and the errors associated with ill-formed data. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on December 8, 2019. Copyright Notice Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License. Carion Expires December 8, 2019 [Page 1] Internet-Draft JSON Schema Language June 2019 Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 1.1. Requirements notation . . . . . . . . . . . . . . . . . . 3 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 2. Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3. Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3.1. Strict instance semantics . . . . . . . . . . . . . . . . 9 3.2. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.3. Forms . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3.1. Empty . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3.2. Ref . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.3.3. Type . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3.4. Enum . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3.5. Elements . . . . . . . . . . . . . . . . . . . . . . 12 3.3.6. Properties . . . . . . . . . . . . . . . . . . . . . 13 3.3.7. Values . . . . . . . . . . . . . . . . . . . . . . . 16 3.3.8. Discriminator . . . . . . . . . . . . . . . . . . . . 16 4. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 20 5. Security Considerations . . . . . . . . . . . . . . . . . . . 20 6. Normative References . . . . . . . . . . . . . . . . . . . . 20 Appendix A. Comparison with CDDL . . . . . . . . . . . . . . . . 21 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 24 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 24 1. Introduction This document describes a schema language for JSON [RFC8259] called JSON Schema Language (JSL). The goals of JSL are to: o Provide an unambiguous description of the overall structure of a JSON document. o Be able to describe common JSON datatypes and structures. o Provide a single format that is readable and editable by both humans and machines, and which can be embedded within other JSON documents. o Enable code generation from schemas. o Provide a standardized format for errors when data does not conform with a schema. JSL is intentionally designed as a rather minimal schema language. For example, JSL is homoiconic (it both describes, and is written in, Carion Expires December 8, 2019 [Page 2] Internet-Draft JSON Schema Language June 2019 JSON) yet is incapable of describing in detail its own structure. By keeping the expressiveness of the schema language minimal, JSL makes code generation and standardized errors easier to implement. It is expected that for many use-cases, a schema language of JSL's expressiveness is sufficient. Where a more expressive language is required, alternatives exist in CDDL and others. This document has the following structure: The syntax of JSL is defined in Section 2. Section 3 describes the semantics of JSL; this includes determining whether some data satisfies a schema and what errors should be produced when the data is unsatisfactory. Appendix A presents various JSL schemas and their CDDL equivalents. 1.1. Requirements notation The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this document, are to be interpreted as described in [RFC2119] [RFC8174]. 1.2. Terminology The terms "absolute-URI" and "URI-reference", when they appear in this document, are to be understood as they are defined in [RFC3986]. The term "JSON Pointer", when it appears in this document, is to be understood as it is defined in [RFC6901]. The term "instance", when it appears in this document, refers to a JSON value being validated against a JSL schema. 2. Syntax This section describes when a JSON document is a correct JSL schema. A correct JSL schema MUST match the "schema" CDDL rule described in this section. A JSL schema is a JSON object taking on an appropriate form. It may optionally contain definitions (a mapping from names to schemas) and additional data. schema = { form, ? definitions: { * tstr => schema } } Carion Expires December 8, 2019 [Page 3] Internet-Draft JSON Schema Language June 2019 This is not a correct JSL schema, as its "definitions" object contains a number, which is not a schema: { "definitions": { "foo": 3 }} JSL schemas can take on one of eight forms. These forms are defined so as to be mutually exclusive; a schema cannot satisfy multiple forms at once. form = empty / ref / type / enum / elements / properties / values / discriminator The first form, "empty", is trivial. It is meant for matching any instance: empty = {} Thus, this is a correct schema: {} The second form, "ref", is for when a schema is meant to be defined in terms of something in "definitions": ref = { ref: tstr } In a correct schema, the "ref" value must always refer to a definition at the root level of a schema. Note well: the _root_ level of the schema. Definitions at the non-root level are immaterial. More formally: Let _D_ be the member of the root schema with the name "definitions". For all schemas _S_ of the ref form in the root schema, let _R_ be the value of the member of _S_ with the name "ref". In a correct schema, _D_ MUST exist and MUST have a member with a name equal to _R_. Here is an example of ref's use to avoid re-defining the same thing twice: Carion Expires December 8, 2019 [Page 4] Internet-Draft JSON Schema Language June 2019 { "definitions": { "coordinates": { "properties": { "lat": { "type": "number" }, "lng": { "type": "number" } } } }, "properties": { "user_location": { "ref": "coordinates" }, "server_location": { "ref": "coordinates" } } } However, this schema is incorrect, as it refers to a definition that doesn't exist: { "definitions": { "foo": { "type": "number" }}, "ref": "bar" } This schema is incorrect as well, as it refers to a definition that doesn't exist at the root level. The non-root definition is immaterial: { "definitions": { "foo": { "type": "number" }}, "elements": { "definitions": { "bar": { "type": "number" }}, "ref": "bar" } } The third form, "type", constrains instances to have a particular primitive type. The precise meaning of each of the primitive types is described in Section 3. type = { type: "boolean" / "number" / "string" / "timestamp" } For example, this schema constrains instances to be strings that are correct [RFC3339] timestamps: { "type": "timestamp" } The fourth form, "enum", describes instances whose value must be one of a finite, predetermined set of values: Carion Expires December 8, 2019 [Page 5] Internet-Draft JSON Schema Language June 2019 enum = { enum: [+ tstr] } The values within "[+ tstr]" MUST NOT contain duplicates. Thus, the following is a correct schema: { "enum": ["IN_PROGRESS", "DONE", "CANCELED"] } But this is not a correct schema, as "B" is duplicated: { "enum": ["A", "B", "B"] } The fifth form, "elements", describes instances that must be arrays. A further sub-schema describes the elements of the array. elements = { elements: schema } Here is a schema describing an array of [RFC3339] timestamps: { "elements": { "type": "timestamp" }} The sixth form, "properties", describes JSON objects being used as a "struct". A schema of this form specifies the names of required and optional properties, as well as the schemas each of those properties must satisfy: ; One of properties or optionalProperties may be omitted, ; but not both. properties = with-properties / with-optional-properties with-properties = { properties: * tstr => schema, ? optionalProperties * tstr => schema } with-optional-properties = { ? properties: * tstr => schema, optionalProperties: * tstr => schema } If a schema has both a member named "properties" (with value _P_) and another member named "optionalProperties" (with value _O_), then _O_ and _P_ MUST NOT have any member names in common. This is to prevent ambiguity as to whether a property is optional or required. Thus, this is not a correct schema, as "confusing" appears in both "properties" and "optionalProperties": Carion Expires December 8, 2019 [Page 6] Internet-Draft JSON Schema Language June 2019 { "properties": { "confusing": {} }, "optionalProperties": { "confusing": {} } } Here is a correct schema, describing a paginated list of users: { "properties": { "users": { "elements": { "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "create_time": { "type": "timestamp" } }, "optionalProperties": { "delete_time": { "type": "timestamp" } } } }, "next_page_token": { "type": "string" } } } The seventh form, "values", describes JSON objects being used as an associative array. A schema of this form specifies the form all member values must satisfy, but places no constraints on the member names: values = { values: * tstr => schema } Thus, this is a correct schema, describing a mapping from strings to numbers: { "values": { "type": "number" }} Finally, the eighth form, "discriminator", describes JSON objects being used as a discriminated union. A schema of this form specifies the "tag" (or "discriminator") of the union, as well as a mapping from tag values to the appropriate schema to use. ; Note well: the values of mapping are of the properties form. discriminator = { tag: tstr, mapping: * tstr => properties } To prevent ambiguous or unsatisfiable contstraints on the "tag" of a discriminator, an additional constraint on the discriminator form exists: Carion Expires December 8, 2019 [Page 7] Internet-Draft JSON Schema Language June 2019 Let _T_ be the value of the member with the name "tag", and let _M_ be the value of the member with the name "mapping". Then for all values _S_ of the members of _M_, _S_ must not contain members named "properties" or "optionalProperties" whose values contain members with a name equal to _T_. Thus, this is an incorrect schema, as "event_type" is both the value of "tag" and a member name in one of the mapping member "properties": { "tag": "event_type", "mapping": { "is_event_type_a_string_or_a_number?": { "properties": { "event_type": { "type": "number" }} } } } However, this is a correct schema, describing a pattern of data common in JSON-based messaging systems: { "tag": "event_type", "mapping": { "account_deleted": { "properties": { "account_id": { "type": "string" } } }, "account_payment_plan_changed": { "properties": { "account_id": { "type": "string" }, "payment_plan": { "enum": ["FREE", "PAID"] } }, "optionalProperties": { "upgraded_by": { "type": "string" } } } } } 3. Semantics This section describes when an instance is valid against a correct JSL schema, and the standardized errors to produce when an instance is invalid. Carion Expires December 8, 2019 [Page 8] Internet-Draft JSON Schema Language June 2019 3.1. Strict instance semantics Users will have different desired behavior with respect to "unspcecified" members in an instance. For example: { "properties": { "a": { "type": "string" }}} Some users may expect that "{"a": "foo", "b": "bar"}" satisfies the above schema. Others may disagree. JSL addresses this point of contention by leaving it to implementations whether to accept such "unspecified" members, or whether to reject them. Rejecting "unspecified" members is called "strict instance semantics". Whether to use strict instance semantics is not specified within a schema - it is considered out-of-band information. Implementations MAY allow users to choose whether to use strict instance semantics. Implementations SHOULD document whether they use strict instance semantics by default. See Section 3.3.6 for how strict instance semantics affects schema evaluation. 3.2. Errors To facilitate consistent validation error handling, this document specifies a standard error format. Implementations SHOULD support producing errors in this standard form. The standard error format is a JSON array. The order of the elements of this array is not specified. The elements of this array are JSON objects with two members: o A member with the name "instancePath", whose value is a JSON string encoding a JSON Pointer. This JSON Pointer will point to the part of the instance that was rejected. o A member with the name "schemaPath", whose value is a JSON string encoding a JSON Pointer. This JSON Pointer will point to the part of the schema that rejected the instance. The values for "instancePath" and "schemaPath" depend on the form of the schema, and are described in detail in Section 3.3. Carion Expires December 8, 2019 [Page 9] Internet-Draft JSON Schema Language June 2019 3.3. Forms This section describes, for each of the eight JSL schema forms, the rules dictating whether an instance is accepted, as well as the standardized errors to produce when an instance is invalid. The forms a correct schema may take on are formally described in Section 2. 3.3.1. Empty The empty form is meant to describe instances whose values are unknown, unpredictable, or otherwise unconstrained by the schema. If a schema is of the empty form, then it accepts all instances. An empty schema will never produce any errors. 3.3.2. Ref The ref form is for when a schema is meant to be defined in terms of something in the "definitions" of the root schema. The ref form enables schemas to be less repetitive, and also enables describing recursive structures. If a schema is of the ref form, then: o Let _B_ be the root schema containing the schema. o Let _D_ be the member of _B_ with the name "definitions". By Section 2, _D_ exists. o Let _R_ be the value of the schema member with the name "ref". o Let _S_ be the value of the member of _D_ whose name equals _R_. By Section 2, _S_ exists, and is a schema. The schema accepts the instance if and only if _S_ accepts the instance. Otherwise, the standard errors to return in this case are the union of the errors from evaluating _S_ against the instance. For example, the schema: { "definitions": { "a": { "type": "number" }}, "ref": "a" } Carion Expires December 8, 2019 [Page 10] Internet-Draft JSON Schema Language June 2019 Accepts 123 but not false. The standard errors to produce when evaluting false against this schema are: [{ "instancePath": "", "schemaPath": "/definitions/a/type" }] Note that the ref form is defined to only look up definitions at the root level. Thus, with the schema: { "definitions": { "a": { "type": "number" }}, "elements": { "definitions": { "a": { "type": "boolean" }}, "ref": "foo" } } The instance 123 is accepted, and false is rejected. The standard errors to produce when evaluating false against this schema are: [{ "instancePath": "", "schemaPath": "/definitions/a/type" }] Though non-root definitions are not syntactically disallowed in correct schemas, they are entirely immaterial to evaluating references. 3.3.3. Type The type form is meant to describe instances whose value is a boolean, number, string, or timestamp ([RFC3339]). If a schema is of the type form, then let _T_ be the value of the member with the name "type": o If _T_ equals "boolean", then the instance is accepted if it equals "true" or "false". o If _T_ equals "number", then the instance is accepted if it is a JSON number. o If _T_ equals "string", then the instance is accepted if it is a JSON string. o If _T_ equals "timestamp", then the instance is accepted if it is a JSON string encoding a timestamp, as defined by [RFC3339]. If the instance is not accepted, then the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to the schema member with the name "type". Carion Expires December 8, 2019 [Page 11] Internet-Draft JSON Schema Language June 2019 For example: o The schema {"type": "boolean"} accepts false, but rejects 123. o The schema {"type": "number"} accepts 123, but rejects false. o The schema {"type": "string"} accepts "1985-04-12T23:20:50.52Z" and "foo", but rejects 123. o The schema {"type": "timestamp"} accepts "1985-04-12T23:20:50.52Z", but rejects "foo" and 123. To give an example of standardized errors, the standard errors to produce when {"type": "boolean"} is evaluated against 123 is: [{ "instancePath": "", "schemaPath": "/type" }] 3.3.4. Enum The enum form is meant to describe instances whose value must be one of a finite, predetermined set of string values. If a schema is of the enum form, then let _E_ be the value of the schema member with the name "enum". The instance is accepted if and only if it is equal to one of the elements of _E_. If the instance is not accepted, then the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to the schema member with the name "enum". For example, the schema: { "enum": ["PENDING", "DONE", "CANCELED"] } Accepts "PENDING", "DONE", and "CANCELED", but it rejects both 123 and "UNKNOWN" with the standard errors: [{ "instancePath": "", "schemaPath": "/enum" }] 3.3.5. Elements The elements form is meant to describe instances instances that must be arrays. A further sub-schema describes the elements of the array. If a schema is of the elements form, then let _S_ be the value of the schema member with the name "elements". The instance is accepted if and only if all of the following are true: Carion Expires December 8, 2019 [Page 12] Internet-Draft JSON Schema Language June 2019 o The instance is an array. Otherwise, the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to the schema member with the name "elements". o If the instance is an array, then every element of the instance must be accepted by _S_. Otherwise, the standard errors for this case are the union of all the errors arising from evaluating _S_ against elements of the instance. For example, if we have the schema: { "elements": { "type": "number" } } Then the instances [] and [1, 2, 3] are accpeted. If instead we evaluate false against that schema, the standard errors are: [{ "instancePath": "", "schemaPath": "/elements" }] Finally, if we evaluate the instance: [1, 2, "foo", 3, "bar"] The standard errors are: [ { "instancePath": "/2", "schemaPath": "/elements/type" }, { "instancePath": "/4", "schemaPath": "/elements/type" } ] 3.3.6. Properties The properties form is meant to describe JSON objects being used as a "struct". If a schema is of the properties form, then the instance is accepted if and only if all of the following are true: o The instance is an object. Otherwise, the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to the schema member with the name "properties" if such a schema member exists; if such a member doesn't exist, "schemaPath" Carion Expires December 8, 2019 [Page 13] Internet-Draft JSON Schema Language June 2019 shall point to the schema member with the name "optionalProperties". o If the instance is an object and the schema has a member named "properties", then let _P_ be the value of the schema member named "properties". _P_, by Section 2, must be an object. For every member name in _P_, a member of the same name in the instance must exist. Otherwise, the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to the member of _P_ failing the requirement just described. o If the instance is an object, then let _P_ be the value of the schema member named "properties" (if it exists), and _O_ be the value of the schema member named "optionalProperties" (if it exists). For every member _I_ of the instance, find a member with the same name as _I_'s in _P_ or _O_. By Section 2, it is not possible for both _P_ and _O_ to have such a member. If the "discriminator tag exemption" is in effect on _I_ (see Section 3.3.8), then ignore _I_. Otherwise: * If no such member in _P_ or _O_ exists and validation is using strict instance semantics, then the instance is rejected. The standard error for this case has an "instancePath" pointing _I_, and a "schemaPath" pointing to the schema. * If such a member in _P_ or _O_ does exist, then call this member _S_. If _S_ rejects _I_'s value, then the instance is rejected. The standard error for this case is the union of the errors from evaluating _S_ against _I_'s value. An instance may have multiple errors arising from the second and third bullet in the above. In this case, the standard errors are the union of the errors. For example, if we have the schema: Carion Expires December 8, 2019 [Page 14] Internet-Draft JSON Schema Language June 2019 { "properties": { "a": { "type": "string" }, "b": { "type": "string" } }, "optionalProperties": { "c": { "type": "string" }, "d": { "type": "string" } } } Then each of the following instances (one on each line) are accepted: { "a": "foo", "b": "bar" } { "a": "foo", "b": "bar", "c": "baz" } { "a": "foo", "b": "bar", "c": "baz", "d": "quux" } { "a": "foo", "b": "bar", "d": "quux" } If we evaluate the instance 123 against this schema, then the standard errors are: [{ "instancePath": "", "schemaPath": "/properties" }] If instead we evalute the instance: { "b": 3, "c": 3, "e": 3 } The standard errors, using strict instance semantics, are: [ { "instancePath": "", "schemaPath": "/properties/a" }, { "instancePath": "/b", "schemaPath": "/properties/b/type" }, { "instancePath": "/c", "schemaPath": "/optionalProperties/c/type" }, { "instancePath": "/e", "schemaPath": "" } ] If we the same instance were evaluated, but without strict instance semantics, the final element of the above array of errors would not be present. Carion Expires December 8, 2019 [Page 15] Internet-Draft JSON Schema Language June 2019 3.3.7. Values The elements form is meant to describe instances that are JSON objects being used as an associative array. If a schema is of the values form, then let _S_ be the value of the schema member with the name "values". The instance is accepted if and only if all of the following are true: o The instance is an object. Otherwise, the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to the schema member with the name "values". o If the instance is an object, then every member value of the instance must be accepted by _S_. Otherwise, the standard errors for this case are the union of all the errors arising from evaluating _S_ against member values of the instance. For example, if we have the schema: { "values": { "type": "number" } } Then the instances {} and {"a": 1, "b": 2} are accpeted. If instead we evaluate false against that schema, the standard errors are: [{ "instancePath": "", "schemaPath": "/values" }] Finally, if we evaluate the instance: { "a": 1, "b": 2, "c": "foo", "d": 3, "e": "bar" } The standard errors are: [ { "instancePath": "/c", "schemaPath": "/values/type" }, { "instancePath": "/e", "schemaPath": "/values/type" } ] 3.3.8. Discriminator The discriminator form is meant to describe JSON objects being used in a fashion similar to a discriminated union construct in C-like languages. When a schema is of the "discriminator" form, it validates: Carion Expires December 8, 2019 [Page 16] Internet-Draft JSON Schema Language June 2019 o That the instance is an object, o That the instance has a particular "tag" property, o That this "tag" property's value is a string within a set of valid values, and o That the instance satisfies another schema, where this other schema is chosen based on the value of the "tag" property. The behavior of the discriminator form is more complex than the other keywords. Readers familiar with CDDL may find the final example in Appendix A helpful in understanding its behavior. What follows here is an English description of the discriminator form's behavior, as well as some examples. If a schema is of the "discriminator" form, then: o Let _D_ be the schema member with the name "discriminator". o Let _T_ be the member of _D_ with the name "tag". o Let _M_ be the member of _D_ with the name "mapping". o Let _I_ be the instance member whose name equals _T_'s value. _I_ may, for some rejected instances, not exist. o Let _S_ be the member of _M_ whose name equals _I_'s value. _S_ may, for some rejected instances, not exist. The instance is accepted if and only if: o The instance is an object. Otherwise, the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to _D_. o If the instance is a JSON object, then _I_ must exist. Otherwise, the standard error for this case shall have an "instancePath" pointing to the instance, and a "schemaPath" pointing to _T_. o If the instance is a JSON object and _I_ exists, _I_'s value must be a string. Carion Expires December 8, 2019 [Page 17] Internet-Draft JSON Schema Language June 2019 Otherwise, the standard error for this case shall have an "instancePath" pointing to _I_, and a "schemaPath" pointing to _T_. o If the instance is a JSON object and _I_ exists and has a string value, then _S_ must exist. Otherwise, the standard error for this case shall have an "instancePath" pointing to _I_, and a "schemaPath" pointing to _M_. o If the instance is a JSON object, _I_ exists, and _S_ exists, then the instance must satisfy _S_'s value. By Section 2, _S_'s value must have the properties form. Apply the "discriminator tag exemption" afforded in Section 3.3.6 to _I_ when evaluating whether the instance satisfies _S_'s value. Otherwise, the standard errors for this case shall be standard errors from evaluating _S_'s value against the instance. Each of the list items above are defined to be mutually exclusive. For the same instance and schema, only one of the list items above will apply. To illustrate the discriminator form, if we have the schema: { "discriminator": { "tag": "version", "mapping": { "v1": { "properties": { "a": { "type": "number" } } }, "v2": { "properties": { "a": { "type": "string" } } } } } } Then if we evaluate the instance: "example" Carion Expires December 8, 2019 [Page 18] Internet-Draft JSON Schema Language June 2019 Against this schema, the standard errors are: [{ "instancePath": "", "schemaPath": "/discriminator" }] (This is the case of the instance not being an object.) If we instead evaluate the instance: {} Then the standard errors are: [{ "instancePath": "", "schemaPath": "/discriminator/tag" }] (This is the case of _I_ not existing.) If we instead evaluate the instance: { "version": 1 } Then the standard errors are: [{ "instancePath": "/version", "schemaPath": "/discriminator/tag" }] (This is the case of _I_ existing, but having a string value.) If we instead evaluate the instance: { "version": "v3" } Then the standard errors are: [ { "instancePath": "/version", "schemaPath": "/discriminator/mapping" } ] (This is the case of _I_ existing and having a string value, but _S_ not existing.) If the instance evaluated were: { "version": "v2", "a": 3 } Then the standard errors are: Carion Expires December 8, 2019 [Page 19] Internet-Draft JSON Schema Language June 2019 [ { "instancePath": "/a", "schemaPath": "/discriminator/mapping/v2/properties/a/type" } ] (This is the case of _I_ and _S_ existing, but the instance not satisfying _S_'s value.) Finally, if instead the instance were: { "version": "v2", "a": "foo" } Then the instance satisfies the schema. No standard errors are returned. This would be the case even if evaluation were using strict instance semantics, as the "discriminator tag exemption" would ensure that "version" is not treated as an unexpected property when evaluating the instance against _S_'s value. 4. IANA Considerations No IANA considerations. 5. Security Considerations Implementations of JSON Schema Language will necessarily be manipulating JSON data. Therefore, the security considerations of [RFC8259] are all relevant here. Implementations which evaluate user-inputted schemas SHOULD implement mechanisms to detect, and abort, circular references which might cause a naive implementation to go into an infinite loop. Without such mechanisms, implementations may be vulnerable to denial-of- service attacks. 6. Normative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, . Carion Expires December 8, 2019 [Page 20] Internet-Draft JSON Schema Language June 2019 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, . [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., "JavaScript Object Notation (JSON) Pointer", RFC 6901, DOI 10.17487/RFC6901, April 2013, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, . Appendix A. Comparison with CDDL This appendix is informative. To aid the reader familiar with CDDL, this section illustrates how JSL works by presenting JSL schemas and CDDL schemas which accept and reject the same instances. The JSL schema {} accepts the same instances as the CDDL rule: root = any The JSL schema: { "definitions": { "a": { "elements": { "ref": "b" }}, "b": { "type": "number" } }, "elements": { "ref": "a" } } Corresponds to the CDDL schema: Carion Expires December 8, 2019 [Page 21] Internet-Draft JSON Schema Language June 2019 root = [* a] a = [* b] b = number The JSL schema: { "enum": ["PENDING", "DONE", "CANCELED"]} Accepts the same instances as the CDDL rule: root = "PENDING" / "DONE" / "CANCELED" The JSL schema {"type": "boolean"} corresponds to the CDDL rule: root = bool The JSL schema {"type": "number"} corresponds to the CDDL rule: root = number The JSL schema {"type": "string"} corresponds to the CDDL rule: root = tstr The JSL schema {"type": "timestamp"} corresponds to the CDDL rule: root = tdate The JSL schema: { "elements": { "type": "number" }} Corresponds to the CDDL rule: root = [* number] The JSL schema: Carion Expires December 8, 2019 [Page 22] Internet-Draft JSON Schema Language June 2019 { "properties": { "a": { "type": "boolean" }, "b": { "type": "number" } }, "optionalProperties": { "c": { "type": "string" }, "d": { "type": "timestamp" } } } Corresponds to the CDDL rule: root = { a: bool, b: number, ? c: tstr, ? d: tdate } The JSL schema: { "values": { "type": "number" }} Corresponds to the CDDL rule: root = { * tstr => number } Finally, the JSL schema: { "discriminator": { "tag": "a", "mapping": { "foo": { "properties": { "b": { "type": "number" } } }, "bar": { "properties": { "b": { "type": "string" } } } } } } Corresponds to the CDDL rule: root = { a: "foo", b: number } / { a: "bar", b: tstr } Carion Expires December 8, 2019 [Page 23] Internet-Draft JSON Schema Language June 2019 Acknowledgments Thanks to Gary Court, Francis Galiegue, Kris Zyp, Geraint Luff, Jason Desrosiers, Daniel Perrett, Erik Wilde, Ben Hutton, Evgeny Poberezkin, Brad Bowman, Gowry Sankar, Donald Pipowitch, Dave Finlay, Denis Laxalde, Henry Andrews, and Austin Wright for their work on the initial drafts of JSON Schema, which inspired JSON Schema Language. Thanks to Tim Bray and Carsten Bormann for their help on JSON Schema Language. Author's Address Ulysse Carion Email: ulyssecarion@gmail.com Carion Expires December 8, 2019 [Page 24]