idnits 2.17.1 draft-json-schema-language-02.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The abstract seems to contain references ([RFC8259]), which it shouldn't. Please replace those with straight textual mentions of the documents in question. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == The document seems to lack the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords. (The document does seem to have the reference to RFC 2119 which the ID-Checklist requires). == Couldn't figure out when the document was first submitted -- there may comments or warnings related to the use of a disclaimer for pre-RFC5378 work that could not be issued because of this. Please check the Legal Provisions document at https://trustee.ietf.org/license-info to determine if you need the pre-RFC5378 disclaimer. -- The document date (July 18, 2019) is 1742 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Looks like a reference, but probably isn't: '1' on line 676 -- Looks like a reference, but probably isn't: '2' on line 676 -- Looks like a reference, but probably isn't: '3' on line 676 Summary: 1 error (**), 0 flaws (~~), 3 warnings (==), 4 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 JSON Working Group U. Carion 3 Internet-Draft July 18, 2019 4 Intended status: Standards Track 5 Expires: January 19, 2020 7 JSON Schema Language 8 draft-json-schema-language-02 10 Abstract 12 JavaScript Object Notation (JSON) Schema Language is a portable 13 method for describing the format of JSON ([RFC8259], JavaScript 14 Object Notation) data and the errors associated with ill-formed data. 16 Status of This Memo 18 This Internet-Draft is submitted in full conformance with the 19 provisions of BCP 78 and BCP 79. 21 Internet-Drafts are working documents of the Internet Engineering 22 Task Force (IETF). Note that other groups may also distribute 23 working documents as Internet-Drafts. The list of current Internet- 24 Drafts is at https://datatracker.ietf.org/drafts/current/. 26 Internet-Drafts are draft documents valid for a maximum of six months 27 and may be updated, replaced, or obsoleted by other documents at any 28 time. It is inappropriate to use Internet-Drafts as reference 29 material or to cite them other than as "work in progress." 31 This Internet-Draft will expire on January 19, 2020. 33 Copyright Notice 35 Copyright (c) 2019 IETF Trust and the persons identified as the 36 document authors. All rights reserved. 38 This document is subject to BCP 78 and the IETF Trust's Legal 39 Provisions Relating to IETF Documents 40 (https://trustee.ietf.org/license-info) in effect on the date of 41 publication of this document. Please review these documents 42 carefully, as they describe your rights and restrictions with respect 43 to this document. Code Components extracted from this document must 44 include Simplified BSD License text as described in Section 4.e of 45 the Trust Legal Provisions and are provided without warranty as 46 described in the Simplified BSD License. 48 Table of Contents 50 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 51 1.1. Requirements notation . . . . . . . . . . . . . . . . . . 3 52 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 53 2. Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 54 3. Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . 9 55 3.1. Strict instance semantics . . . . . . . . . . . . . . . . 9 56 3.2. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 10 57 3.3. Forms . . . . . . . . . . . . . . . . . . . . . . . . . . 10 58 3.3.1. Empty . . . . . . . . . . . . . . . . . . . . . . . . 10 59 3.3.2. Ref . . . . . . . . . . . . . . . . . . . . . . . . . 10 60 3.3.3. Type . . . . . . . . . . . . . . . . . . . . . . . . 12 61 3.3.4. Enum . . . . . . . . . . . . . . . . . . . . . . . . 14 62 3.3.5. Elements . . . . . . . . . . . . . . . . . . . . . . 14 63 3.3.6. Properties . . . . . . . . . . . . . . . . . . . . . 15 64 3.3.7. Values . . . . . . . . . . . . . . . . . . . . . . . 18 65 3.3.8. Discriminator . . . . . . . . . . . . . . . . . . . . 18 66 4. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 22 67 5. Security Considerations . . . . . . . . . . . . . . . . . . . 22 68 6. References . . . . . . . . . . . . . . . . . . . . . . . . . 22 69 6.1. Normative References . . . . . . . . . . . . . . . . . . 22 70 6.2. Informative References . . . . . . . . . . . . . . . . . 23 71 Appendix A. Comparison with CDDL . . . . . . . . . . . . . . . . 23 72 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 26 73 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 26 75 1. Introduction 77 This document describes a schema language for JSON [RFC8259] called 78 JSON Schema Language (JSL). 80 The goals of JSL are to: 82 o Provide an unambiguous description of the overall structure of a 83 JSON document. 85 o Be able to describe common JSON datatypes and structures. 87 o Provide a single format that is readable and editable by both 88 humans and machines, and which can be embedded within other JSON 89 documents. 91 o Enable code generation from schemas. 93 o Provide a standardized format for errors when data does not 94 conform with a schema. 96 JSL is intentionally designed as a rather minimal schema language. 97 For example, JSL is homoiconic (it both describes, and is written in, 98 JSON) yet is incapable of describing in detail its own structure. By 99 keeping the expressiveness of the schema language minimal, JSL makes 100 code generation and standardized errors easier to implement. 102 It is expected that for many use-cases, a schema language of JSL's 103 expressiveness is sufficient. Where a more expressive language is 104 required, alternatives exist in CDDL ([RFC8610], Concise Data 105 Definition Language) and others. 107 This document has the following structure: 109 The syntax of JSL is defined in Section 2. Section 3 describes the 110 semantics of JSL; this includes determining whether some data 111 satisfies a schema and what errors should be produced when the data 112 is unsatisfactory. Appendix A presents various JSL schemas and their 113 CDDL equivalents. 115 1.1. Requirements notation 117 The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, 118 SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this 119 document, are to be interpreted as described in [RFC2119] [RFC8174]. 121 1.2. Terminology 123 The terms "absolute-URI" and "URI-reference", when they appear in 124 this document, are to be understood as they are defined in [RFC3986]. 126 The term "JSON Pointer", when it appears in this document, is to be 127 understood as it is defined in [RFC6901]. 129 The term "instance", when it appears in this document, refers to a 130 JSON value being validated against a JSL schema. 132 2. Syntax 134 This section describes when a JSON document is a correct JSL schema. 136 JSL schemas may recurisvely contain other schemas. In this document, 137 a "root schema" is one which is not contained within another schema, 138 i.e. it is "top level". 140 A correct JSL schema MUST match the "schema" CDDL rule described in 141 this section. A JSL schema is a JSON object taking on an appropriate 142 form. It may optionally contain definitions (a mapping from names to 143 schemas) and additional data. 145 schema = { 146 form, 147 ? definitions: { * tstr => schema } 148 } 150 This is not a correct JSL schema, as its "definitions" object 151 contains a number, which is not a schema: 153 { "definitions": { "foo": 3 }} 155 JSL schemas can take on one of eight forms. These forms are defined 156 so as to be mutually exclusive; a schema cannot satisfy multiple 157 forms at once. 159 form = empty / 160 ref / 161 type / 162 enum / 163 elements / 164 properties / 165 values / 166 discriminator 168 The first form, "empty", is trivial. It is meant for matching any 169 instance: 171 empty = {} 173 Thus, this is a correct schema: 175 {} 177 The second form, "ref", is for when a schema is meant to be defined 178 in terms of something in "definitions": 180 ref = { ref: tstr } 182 For a schema to be correct, the "ref" value must refer to one of the 183 definitions found at the root level of the schema it appears in. 184 More formally, for a schema of the "ref" form: 186 o Let _B_ be the root schema containing the schema, or the schema 187 itself if it is a root schema. 189 o Let _R_ be the value of the member of _S_ with the name "ref". 191 If the schema is correct, then _B_ must have a member _D_ with the 192 name "definitions", and _D_ must contain a member whose name equals 193 _R_. 195 Here is a correct example of "ref" being used to avoid re-defining 196 the same thing twice: 198 { 199 "definitions": { 200 "coordinates": { 201 "properties": { 202 "lat": { "type": "number" }, 203 "lng": { "type": "number" } 204 } 205 } 206 }, 207 "properties": { 208 "user_location": { "ref": "coordinates" }, 209 "server_location": { "ref": "coordinates" } 210 } 211 } 213 However, this schema is incorrect, as it refers to a definition that 214 doesn't exist: 216 { 217 "definitions": { "foo": { "type": "number" }}, 218 "ref": "bar" 219 } 221 This schema is incorrect as well, as it refers to a definition that 222 doesn't exist at the root level. The non-root definition is 223 immaterial: 225 { 226 "definitions": { "foo": { "type": "number" }}, 227 "elements": { 228 "definitions": { "bar": { "type": "number" }}, 229 "ref": "bar" 230 } 231 } 233 The third form, "type", constrains instances to have a particular 234 primitive type. The precise meaning of each of the primitive types 235 is described in Section 3. 237 type = { type: "boolean" / num_type / "string" / "timestamp" } 238 num_type = "number" / "float32" / "float64" / 239 "int8" / "uint8" / "int16" / "uint16" / "int32" / "uint32" 241 For example, this schema constrains instances to be strings that are 242 correct [RFC3339] timestamps: 244 { "type": "timestamp" } 246 The fourth form, "enum", describes instances whose value must be one 247 of a finite, predetermined set of values: 249 enum = { enum: [+ tstr] } 251 The values within "[+ tstr]" MUST NOT contain duplicates. Thus, the 252 following is a correct schema: 254 { "enum": ["IN_PROGRESS", "DONE", "CANCELED"] } 256 But this is not a correct schema, as "B" is duplicated: 258 { "enum": ["A", "B", "B"] } 260 The fifth form, "elements", describes instances that must be arrays. 261 A further sub-schema describes the elements of the array. 263 elements = { elements: schema } 265 Here is a schema describing an array of [RFC3339] timestamps: 267 { "elements": { "type": "timestamp" }} 269 The sixth form, "properties", describes JSON objects being used as a 270 "struct". A schema of this form specifies the names of required and 271 optional properties, as well as the schemas each of those properties 272 must satisfy: 274 ; One of properties or optionalProperties may be omitted, 275 ; but not both. 276 properties = with-properties / with-optional-properties 278 with-properties = { 279 properties: * tstr => schema, 280 ? optionalProperties * tstr => schema 281 } 283 with-optional-properties = { 284 ? properties: * tstr => schema, 285 optionalProperties: * tstr => schema 286 } 288 If a schema has both a member named "properties" (with value _P_) and 289 another member named "optionalProperties" (with value _O_), then _O_ 290 and _P_ MUST NOT have any member names in common. This is to prevent 291 ambiguity as to whether a property is optional or required. 293 Thus, this is not a correct schema, as "confusing" appears in both 294 "properties" and "optionalProperties": 296 { 297 "properties": { "confusing": {} }, 298 "optionalProperties": { "confusing": {} } 299 } 301 Here is a correct schema, describing a paginated list of users: 303 { 304 "properties": { 305 "users": { 306 "elements": { 307 "properties": { 308 "id": { "type": "string" }, 309 "name": { "type": "string" }, 310 "create_time": { "type": "timestamp" } 311 }, 312 "optionalProperties": { 313 "delete_time": { "type": "timestamp" } 314 } 315 } 316 }, 317 "next_page_token": { "type": "string" } 318 } 319 } 320 The seventh form, "values", describes JSON objects being used as an 321 associative array. A schema of this form specifies the form all 322 member values must satisfy, but places no constraints on the member 323 names: 325 values = { values: * tstr => schema } 327 Thus, this is a correct schema, describing a mapping from strings to 328 numbers: 330 { "values": { "type": "number" }} 332 Finally, the eighth form, "discriminator", describes JSON objects 333 being used as a discriminated union. A schema of this form specifies 334 the "tag" (or "discriminator") of the union, as well as a mapping 335 from tag values to the appropriate schema to use. 337 ; Note well: the values of mapping are of the properties form. 338 discriminator = { tag: tstr, mapping: * tstr => properties } 340 To prevent ambiguous or unsatisfiable contstraints on the "tag" of a 341 discriminator, an additional constraint on schemas of the 342 discriminator form exists. For schemas of the discriminator form: 344 o Let _D_ be the schema member with the name "discriminator". 346 o Let _T_ be the member of _D_ with the name "tag". 348 o Let _M_ be the member of _D_ with the name "mapping". 350 If the schema is correct, then for all member values _S_ of _M_, _S_ 351 must not have any member named "properties" or "optionalProperties" 352 with a name equal to _T_'s value. 354 Thus, this is an incorrect schema, as "event_type" is both the value 355 of "tag" and a member name in one of the mapping member "properties": 357 { 358 "tag": "event_type", 359 "mapping": { 360 "is_event_type_a_string_or_a_number?": { 361 "properties": { "event_type": { "type": "number" }} 362 } 363 } 364 } 366 However, this is a correct schema, describing a pattern of data 367 common in JSON-based messaging systems: 369 { 370 "tag": "event_type", 371 "mapping": { 372 "account_deleted": { 373 "properties": { 374 "account_id": { "type": "string" } 375 } 376 }, 377 "account_payment_plan_changed": { 378 "properties": { 379 "account_id": { "type": "string" }, 380 "payment_plan": { "enum": ["FREE", "PAID"] } 381 }, 382 "optionalProperties": { 383 "upgraded_by": { "type": "string" } 384 } 385 } 386 } 387 } 389 3. Semantics 391 This section describes when an instance is valid against a correct 392 JSL schema, and the standardized errors to produce when an instance 393 is invalid. 395 3.1. Strict instance semantics 397 Users will have different desired behavior with respect to 398 "unspcecified" members in an instance. For example: 400 { "properties": { "a": { "type": "string" }}} 402 Some users may expect that {"a": "foo", "b": "bar"} satisfies the 403 above schema. Others may disagree. JSL addresses this point of 404 contention by leaving it to implementations whether to accept such 405 "unspecified" members, or whether to reject them. 407 Rejecting "unspecified" members is called "strict instance 408 semantics". Whether to use strict instance semantics is not 409 specified within a schema - it is considered out-of-band information. 411 Implementations MAY allow users to choose whether to use strict 412 instance semantics. Implementations SHOULD document whether they use 413 strict instance semantics by default. 415 See Section 3.3.6 for how strict instance semantics affects schema 416 evaluation. 418 3.2. Errors 420 To facilitate consistent validation error handling, this document 421 specifies a standard error format. Implementations SHOULD support 422 producing errors in this standard form. 424 The standard error format is a JSON array. The order of the elements 425 of this array is not specified. The elements of this array are JSON 426 objects with two members: 428 o A member with the name "instancePath", whose value is a JSON 429 string encoding a JSON Pointer. This JSON Pointer will point to 430 the part of the instance that was rejected. 432 o A member with the name "schemaPath", whose value is a JSON string 433 encoding a JSON Pointer. This JSON Pointer will point to the part 434 of the schema that rejected the instance. 436 The values for "instancePath" and "schemaPath" depend on the form of 437 the schema, and are described in detail in Section 3.3. 439 3.3. Forms 441 This section describes, for each of the eight JSL schema forms, the 442 rules dictating whether an instance is accepted, as well as the 443 standardized errors to produce when an instance is invalid. 445 The forms a correct schema may take on are formally described in 446 Section 2. 448 3.3.1. Empty 450 The empty form is meant to describe instances whose values are 451 unknown, unpredictable, or otherwise unconstrained by the schema. 453 If a schema is of the empty form, then it accepts all instances. An 454 empty schema will never produce any errors. 456 3.3.2. Ref 458 The ref form is for when a schema is meant to be defined in terms of 459 something in the "definitions" of the root schema. The ref form 460 enables schemas to be less repetitive, and also enables describing 461 recursive structures. 463 If a schema is of the ref form, then: 465 o Let _B_ be the root schema containing the schema, or the schema 466 itself if it is a root schema. 468 o Let _D_ be the member of _B_ with the name "definitions". By 469 Section 2, _D_ exists. 471 o Let _R_ be the value of the schema member with the name "ref". 473 o Let _S_ be the value of the member of _D_ whose name equals _R_. 474 By Section 2, _S_ exists, and is a schema. 476 The schema accepts the instance if and only if _S_ accepts the 477 instance. Otherwise, the standard errors to return in this case are 478 the union of the errors from evaluating _S_ against the instance. 480 For example, the schema: 482 { 483 "definitions": { "a": { "type": "number" }}, 484 "ref": "a" 485 } 487 Accepts 123 but not false. The standard errors to produce when 488 evaluting false against this schema are: 490 [{ "instancePath": "", "schemaPath": "/definitions/a/type" }] 492 Note that the ref form is defined to only look up definitions at the 493 root level. Thus, with the schema: 495 { 496 "definitions": { "a": { "type": "number" }}, 497 "elements": { 498 "definitions": { "a": { "type": "boolean" }}, 499 "ref": "foo" 500 } 501 } 503 The instance 123 is accepted, and false is rejected. The standard 504 errors to produce when evaluating false against this schema are: 506 [{ "instancePath": "", "schemaPath": "/definitions/a/type" }] 508 Though non-root definitions are not syntactically disallowed in 509 correct schemas, they are entirely immaterial to evaluating 510 references. 512 3.3.3. Type 514 The type form is meant to describe instances whose value is a 515 boolean, number, string, or timestamp ([RFC3339]). 517 If a schema is of the type form, then let _T_ be the value of the 518 member with the name "type". The following table describes whether 519 the instance is accepted, as a function of _T_'s value: 521 +-------------------+----------------------------------------------+ 522 | If _T_ equals ... | then the instance is accepted if it is ... | 523 +-------------------+----------------------------------------------+ 524 | boolean | equal to "true" or "false" | 525 | | | 526 | number | a JSON number | 527 | | | 528 | float32 | a JSON number | 529 | | | 530 | float64 | a JSON number | 531 | | | 532 | int8 | See Table 2 | 533 | | | 534 | uint8 | See Table 2 | 535 | | | 536 | int16 | See Table 2 | 537 | | | 538 | uint16 | See Table 2 | 539 | | | 540 | int32 | See Table 2 | 541 | | | 542 | uint32 | See Table 2 | 543 | | | 544 | int64 | See Table 2 | 545 | | | 546 | uint64 | See Table 2 | 547 | | | 548 | string | a JSON string | 549 | | | 550 | timestamp | a JSON string encoding a [RFC3339] timestamp | 551 +-------------------+----------------------------------------------+ 553 Table 1: Accepted Values for Type 555 "float32" and "float64" are distinguished from "number" in their 556 intent. "float32" indicates data intended to be processed as an IEEE 557 754 single-precision float, whereas "float64" indicates data intended 558 to be processed as an IEEE 754 double-precision float. "number" 559 indicates no specific intent. Tools which generate code from JSL 560 schemas will likely produce different code for "float32", "float64", 561 and "number". 563 If _T_ starts with "int" or "uint", then the instance is accepted if 564 and only if it is a JSON number encoding a value with zero fractional 565 part. Depending on the value of _T_, this encoded number must 566 additionally fall within a particular range: 568 +--------+----------------------------+----------------------------+ 569 | _T_ | Minimum Value (Inclusive) | Maximum Value (Inclusive) | 570 +--------+----------------------------+----------------------------+ 571 | int8 | -128 | 127 | 572 | | | | 573 | uint8 | 0 | 255 | 574 | | | | 575 | int16 | -32,768 | 32,767 | 576 | | | | 577 | uint16 | 0 | 65,535 | 578 | | | | 579 | int32 | -2,147,483,648 | 2,147,483,647 | 580 | | | | 581 | uint32 | 0 | 4,294,967,295 | 582 | | | | 583 | int64 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 | 584 | | | | 585 | uint64 | 0 | 18,446,744,073,709,551,615 | 586 +--------+----------------------------+----------------------------+ 588 Table 2: Ranges for Integer Types 590 Note that both 10 and 10.0 encode values with zero fractional part. 591 10.5 encodes a number with a non-zero fractional part. Therefore 592 {"type": "int8"} accepts 10 and 10.0, but not 10.5. 594 As an interoperability consideration, applications using the I-JSON 595 profile of JSON ([RFC7493]) cannot presume numerical precision beyond 596 that of IEEE 754 double-precision floats. Therefore, these 597 applications cannot represent the full range of "int64" or "uint64" 598 without assuming possible loss of precision. For these applications, 599 some instances may be erroneously accepted or rejected due to loss of 600 precision. 602 If the instance is not accepted, then the standard error for this 603 case shall have an "instancePath" pointing to the instance, and a 604 "schemaPath" pointing to the schema member with the name "type". 606 For example: 608 o The schema {"type": "boolean"} accepts false, but rejects 127. 610 o The schema {"type": "number"} accepts 10.5, 127 and 128, but 611 rejects false. 613 o The schema {"type": "int8"} accepts 127, but rejects 10.5, 128 and 614 false. 616 o The schema {"type": "string"} accepts "1985-04-12T23:20:50.52Z" 617 and "foo", but rejects 127. 619 o The schema {"type": "timestamp"} accepts 620 "1985-04-12T23:20:50.52Z", but rejects "foo" and 127. 622 In all of the rejected examples just given, the standard error to 623 produce is: 625 [{ "instancePath": "", "schemaPath": "/type" }] 627 3.3.4. Enum 629 The enum form is meant to describe instances whose value must be one 630 of a finite, predetermined set of string values. 632 If a schema is of the enum form, then let _E_ be the value of the 633 schema member with the name "enum". The instance is accepted if and 634 only if it is equal to one of the elements of _E_. 636 If the instance is not accepted, then the standard error for this 637 case shall have an "instancePath" pointing to the instance, and a 638 "schemaPath" pointing to the schema member with the name "enum". 640 For example, the schema: 642 { "enum": ["PENDING", "DONE", "CANCELED"] } 644 Accepts "PENDING", "DONE", and "CANCELED", but it rejects both 123 645 and "UNKNOWN" with the standard errors: 647 [{ "instancePath": "", "schemaPath": "/enum" }] 649 3.3.5. Elements 651 The elements form is meant to describe instances that must be arrays. 652 A further sub-schema describes the elements of the array. 654 If a schema is of the elements form, then let _S_ be the value of the 655 schema member with the name "elements". The instance is accepted if 656 and only if all of the following are true: 658 o The instance is an array. Otherwise, the standard error for this 659 case shall have an "instancePath" pointing to the instance, and a 660 "schemaPath" pointing to the schema member with the name 661 "elements". 663 o If the instance is an array, then every element of the instance 664 must be accepted by _S_. Otherwise, the standard errors for this 665 case are the union of all the errors arising from evaluating _S_ 666 against elements of the instance. 668 For example, if we have the schema: 670 { 671 "elements": { 672 "type": "number" 673 } 674 } 676 Then the instances [] and [1, 2, 3] are accepted. If instead we 677 evaluate false against that schema, the standard errors are: 679 [{ "instancePath": "", "schemaPath": "/elements" }] 681 Finally, if we evaluate the instance: 683 [1, 2, "foo", 3, "bar"] 685 The standard errors are: 687 [ 688 { "instancePath": "/2", "schemaPath": "/elements/type" }, 689 { "instancePath": "/4", "schemaPath": "/elements/type" } 690 ] 692 3.3.6. Properties 694 The properties form is meant to describe JSON objects being used as a 695 "struct". 697 If a schema is of the properties form, then the instance is accepted 698 if and only if all of the following are true: 700 o The instance is an object. 702 Otherwise, the standard error for this case shall have an 703 "instancePath" pointing to the instance, and a "schemaPath" 704 pointing to the schema member with the name "properties" if such a 705 schema member exists; if such a member doesn't exist, "schemaPath" 706 shall point to the schema member with the name 707 "optionalProperties". 709 o If the instance is an object and the schema has a member named 710 "properties", then let _P_ be the value of the schema member named 711 "properties". _P_, by Section 2, must be an object. For every 712 member name in _P_, a member of the same name in the instance must 713 exist. 715 Otherwise, the standard error for this case shall have an 716 "instancePath" pointing to the instance, and a "schemaPath" 717 pointing to the member of _P_ failing the requirement just 718 described. 720 o If the instance is an object, then let _P_ be the value of the 721 schema member named "properties" (if it exists), and _O_ be the 722 value of the schema member named "optionalProperties" (if it 723 exists). 725 For every member _I_ of the instance, find a member with the same 726 name as _I_'s in _P_ or _O_. By Section 2, it is not possible for 727 both _P_ and _O_ to have such a member. If the "discriminator tag 728 exemption" is in effect on _I_ (see Section 3.3.8), then ignore 729 _I_. Otherwise: 731 * If no such member in _P_ or _O_ exists and validation is using 732 strict instance semantics, then the instance is rejected. 734 The standard error for this case has an "instancePath" pointing 735 _I_, and a "schemaPath" pointing to the schema. 737 * If such a member in _P_ or _O_ does exist, then call this 738 member _S_. If _S_ rejects _I_'s value, then the instance is 739 rejected. 741 The standard error for this case is the union of the errors 742 from evaluating _S_ against _I_'s value. 744 An instance may have multiple errors arising from the second and 745 third bullet in the above. In this case, the standard errors are the 746 union of the errors. 748 For example, if we have the schema: 750 { 751 "properties": { 752 "a": { "type": "string" }, 753 "b": { "type": "string" } 754 }, 755 "optionalProperties": { 756 "c": { "type": "string" }, 757 "d": { "type": "string" } 758 } 759 } 761 Then each of the following instances (one on each line) are accepted: 763 { "a": "foo", "b": "bar" } 764 { "a": "foo", "b": "bar", "c": "baz" } 765 { "a": "foo", "b": "bar", "c": "baz", "d": "quux" } 766 { "a": "foo", "b": "bar", "d": "quux" } 768 If we evaluate the instance 123 against this schema, then the 769 standard errors are: 771 [{ "instancePath": "", "schemaPath": "/properties" }] 773 If instead we evalute the instance: 775 { "b": 3, "c": 3, "e": 3 } 777 The standard errors, using strict instance semantics, are: 779 [ 780 { "instancePath": "", 781 "schemaPath": "/properties/a" }, 782 { "instancePath": "/b", 783 "schemaPath": "/properties/b/type" }, 784 { "instancePath": "/c", 785 "schemaPath": "/optionalProperties/c/type" }, 786 { "instancePath": "/e", 787 "schemaPath": "" } 788 ] 790 If we the same instance were evaluated, but without strict instance 791 semantics, the final element of the above array of errors would not 792 be present. 794 3.3.7. Values 796 The elements form is meant to describe instances that are JSON 797 objects being used as an associative array. 799 If a schema is of the values form, then let _S_ be the value of the 800 schema member with the name "values". The instance is accepted if 801 and only if all of the following are true: 803 o The instance is an object. Otherwise, the standard error for this 804 case shall have an "instancePath" pointing to the instance, and a 805 "schemaPath" pointing to the schema member with the name "values". 807 o If the instance is an object, then every member value of the 808 instance must be accepted by _S_. Otherwise, the standard errors 809 for this case are the union of all the errors arising from 810 evaluating _S_ against member values of the instance. 812 For example, if we have the schema: 814 { 815 "values": { 816 "type": "number" 817 } 818 } 820 Then the instances {} and {"a": 1, "b": 2} are accepted. If instead 821 we evaluate false against that schema, the standard errors are: 823 [{ "instancePath": "", "schemaPath": "/values" }] 825 Finally, if we evaluate the instance: 827 { "a": 1, "b": 2, "c": "foo", "d": 3, "e": "bar" } 829 The standard errors are: 831 [ 832 { "instancePath": "/c", "schemaPath": "/values/type" }, 833 { "instancePath": "/e", "schemaPath": "/values/type" } 834 ] 836 3.3.8. Discriminator 838 The discriminator form is meant to describe JSON objects being used 839 in a fashion similar to a discriminated union construct in C-like 840 languages. When a schema is of the "discriminator" form, it 841 validates: 843 o That the instance is an object, 845 o That the instance has a particular "tag" property, 847 o That this "tag" property's value is a string within a set of valid 848 values, and 850 o That the instance satisfies another schema, where this other 851 schema is chosen based on the value of the "tag" property. 853 The behavior of the discriminator form is more complex than the other 854 keywords. Readers familiar with CDDL may find the final example in 855 Appendix A helpful in understanding its behavior. What follows in 856 this section is a description of the discriminator form's behavior, 857 as well as some examples. 859 If a schema is of the "discriminator" form, then: 861 o Let _D_ be the schema member with the name "discriminator". 863 o Let _T_ be the member of _D_ with the name "tag". 865 o Let _M_ be the member of _D_ with the name "mapping". 867 o Let _I_ be the instance member whose name equals _T_'s value. _I_ 868 may, for some rejected instances, not exist. 870 o Let _S_ be the member of _M_ whose name equals _I_'s value. _S_ 871 may, for some rejected instances, not exist. 873 The instance is accepted if and only if: 875 o The instance is an object. 877 Otherwise, the standard error for this case shall have an 878 "instancePath" pointing to the instance, and a "schemaPath" 879 pointing to _D_. 881 o If the instance is a JSON object, then _I_ must exist. 883 Otherwise, the standard error for this case shall have an 884 "instancePath" pointing to the instance, and a "schemaPath" 885 pointing to _T_. 887 o If the instance is a JSON object and _I_ exists, _I_'s value must 888 be a string. 890 Otherwise, the standard error for this case shall have an 891 "instancePath" pointing to _I_, and a "schemaPath" pointing to 892 _T_. 894 o If the instance is a JSON object and _I_ exists and has a string 895 value, then _S_ must exist. 897 Otherwise, the standard error for this case shall have an 898 "instancePath" pointing to _I_, and a "schemaPath" pointing to 899 _M_. 901 o If the instance is a JSON object, _I_ exists, and _S_ exists, then 902 the instance must satisfy _S_'s value. By Section 2, _S_'s value 903 must have the properties form. Apply the "discriminator tag 904 exemption" afforded in Section 3.3.6 to _I_ when evaluating 905 whether the instance satisfies _S_'s value. 907 Otherwise, the standard errors for this case shall be standard 908 errors from evaluating _S_'s value against the instance. 910 Each of the list items above are defined to be mutually exclusive. 911 For the same instance and schema, only one of the list items above 912 will apply. 914 To illustrate the discriminator form, if we have the schema: 916 { 917 "discriminator": { 918 "tag": "version", 919 "mapping": { 920 "v1": { 921 "properties": { 922 "a": { "type": "number" } 923 } 924 }, 925 "v2": { 926 "properties": { 927 "a": { "type": "string" } 928 } 929 } 930 } 931 } 932 } 934 Then if we evaluate the instance: 936 "example" 937 Against this schema, the standard errors are: 939 [{ "instancePath": "", "schemaPath": "/discriminator" }] 941 (This is the case of the instance not being an object.) 943 If we instead evaluate the instance: 945 {} 947 Then the standard errors are: 949 [{ "instancePath": "", "schemaPath": "/discriminator/tag" }] 951 (This is the case of _I_ not existing.) 953 If we instead evaluate the instance: 955 { "version": 1 } 957 Then the standard errors are: 959 [{ "instancePath": "/version", "schemaPath": "/discriminator/tag" }] 961 (This is the case of _I_ existing, but having a string value.) 963 If we instead evaluate the instance: 965 { "version": "v3" } 967 Then the standard errors are: 969 [ 970 { "instancePath": "/version", 971 "schemaPath": "/discriminator/mapping" } 972 ] 974 (This is the case of _I_ existing and having a string value, but _S_ 975 not existing.) 977 If the instance evaluated were: 979 { "version": "v2", "a": 3 } 981 Then the standard errors are: 983 [ 984 { 985 "instancePath": "/a", 986 "schemaPath": "/discriminator/mapping/v2/properties/a/type" 987 } 988 ] 990 (This is the case of _I_ and _S_ existing, but the instance not 991 satisfying _S_'s value.) 993 Finally, if instead the instance were: 995 { "version": "v2", "a": "foo" } 997 Then the instance satisfies the schema. No standard errors are 998 returned. This would be the case even if evaluation were using 999 strict instance semantics, as the "discriminator tag exemption" would 1000 ensure that "version" is not treated as an unexpected property when 1001 evaluating the instance against _S_'s value. 1003 4. IANA Considerations 1005 No IANA considerations. 1007 5. Security Considerations 1009 Implementations of JSON Schema Language will necessarily be 1010 manipulating JSON data. Therefore, the security considerations of 1011 [RFC8259] are all relevant here. 1013 Implementations which evaluate user-inputted schemas SHOULD implement 1014 mechanisms to detect, and abort, circular references which might 1015 cause a naive implementation to go into an infinite loop. Without 1016 such mechanisms, implementations may be vulnerable to denial-of- 1017 service attacks. 1019 6. References 1021 6.1. Normative References 1023 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 1024 Requirement Levels", BCP 14, RFC 2119, 1025 DOI 10.17487/RFC2119, March 1997, 1026 . 1028 [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: 1029 Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, 1030 . 1032 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 1033 Resource Identifier (URI): Generic Syntax", STD 66, 1034 RFC 3986, DOI 10.17487/RFC3986, January 2005, 1035 . 1037 [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., 1038 "JavaScript Object Notation (JSON) Pointer", RFC 6901, 1039 DOI 10.17487/RFC6901, April 2013, 1040 . 1042 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 1043 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 1044 May 2017, . 1046 [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 1047 Interchange Format", STD 90, RFC 8259, 1048 DOI 10.17487/RFC8259, December 2017, 1049 . 1051 [RFC8610] Birkholz, H., Vigano, C., and C. Bormann, "Concise Data 1052 Definition Language (CDDL): A Notational Convention to 1053 Express Concise Binary Object Representation (CBOR) and 1054 JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610, 1055 June 2019, . 1057 6.2. Informative References 1059 [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, 1060 DOI 10.17487/RFC7493, March 2015, 1061 . 1063 Appendix A. Comparison with CDDL 1065 This appendix is informative. 1067 To aid the reader familiar with CDDL, this section illustrates how 1068 JSL works by presenting JSL schemas and CDDL schemas which accept and 1069 reject the same instances. 1071 The JSL schema {} accepts the same instances as the CDDL rule: 1073 root = any 1075 The JSL schema: 1077 { 1078 "definitions": { 1079 "a": { "elements": { "ref": "b" }}, 1080 "b": { "type": "number" } 1081 }, 1082 "elements": { 1083 "ref": "a" 1084 } 1085 } 1087 Corresponds to the CDDL schema: 1089 root = [* a] 1091 a = [* b] 1092 b = number 1094 The JSL schema: 1096 { "enum": ["PENDING", "DONE", "CANCELED"]} 1098 Accepts the same instances as the CDDL rule: 1100 root = "PENDING" / "DONE" / "CANCELED" 1102 The JSL schema {"type": "boolean"} corresponds to the CDDL rule: 1104 root = bool 1106 The JSL schema {"type": "number"} corresponds to the CDDL rule: 1108 root = number 1110 The JSL schema {"type": "string"} corresponds to the CDDL rule: 1112 root = tstr 1114 The JSL schema {"type": "timestamp"} corresponds to the CDDL rule: 1116 root = tdate 1118 The JSL schema: 1120 { "elements": { "type": "number" }} 1122 Corresponds to the CDDL rule: 1124 root = [* number] 1125 The JSL schema: 1127 { 1128 "properties": { 1129 "a": { "type": "boolean" }, 1130 "b": { "type": "number" } 1131 }, 1132 "optionalProperties": { 1133 "c": { "type": "string" }, 1134 "d": { "type": "timestamp" } 1135 } 1136 } 1138 Corresponds to the CDDL rule: 1140 root = { a: bool, b: number, ? c: tstr, ? d: tdate } 1142 The JSL schema: 1144 { "values": { "type": "number" }} 1146 Corresponds to the CDDL rule: 1148 root = { * tstr => number } 1150 Finally, the JSL schema: 1152 { 1153 "discriminator": { 1154 "tag": "a", 1155 "mapping": { 1156 "foo": { 1157 "properties": { 1158 "b": { "type": "number" } 1159 } 1160 }, 1161 "bar": { 1162 "properties": { 1163 "b": { "type": "string" } 1164 } 1165 } 1166 } 1167 } 1168 } 1170 Corresponds to the CDDL rule: 1172 root = { a: "foo", b: number } / { a: "bar", b: tstr } 1174 Acknowledgments 1176 Thanks to Gary Court, Francis Galiegue, Kris Zyp, Geraint Luff, Jason 1177 Desrosiers, Daniel Perrett, Erik Wilde, Ben Hutton, Evgeny 1178 Poberezkin, Brad Bowman, Gowry Sankar, Donald Pipowitch, Dave Finlay, 1179 Denis Laxalde, Henry Andrews, and Austin Wright for their work on the 1180 initial drafts of JSON Schema, which inspired JSON Schema Language. 1182 Thanks to Tim Bray and Carsten Bormann for their help on JSON Schema 1183 Language. 1185 Author's Address 1187 Ulysse Carion 1189 Email: ulyssecarion@gmail.com