idnits 2.17.1 draft-ucarion-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 : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (August 09, 2019) is 1716 days in the past. Is this intentional? Checking references for intended status: Informational ---------------------------------------------------------------------------- -- Looks like a reference, but probably isn't: '1' on line 754 -- Looks like a reference, but probably isn't: '2' on line 754 -- Looks like a reference, but probably isn't: '3' on line 754 Summary: 0 errors (**), 0 flaws (~~), 1 warning (==), 4 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Independent Submission U. Carion 3 Internet-Draft August 09, 2019 4 Intended status: Informational 5 Expires: February 10, 2020 7 JSON Schema Language (JSL) 8 draft-ucarion-json-schema-language-02 10 Abstract 12 JSON Schema Language (JSL) is a portable method for describing the 13 format of JavaScript Object Notation (JSON) data and the errors 14 associated with ill-formed data. JSL is designed to enable code 15 generation from schemas. 17 Status of This Memo 19 This Internet-Draft is submitted in full conformance with the 20 provisions of BCP 78 and BCP 79. 22 Internet-Drafts are working documents of the Internet Engineering 23 Task Force (IETF). Note that other groups may also distribute 24 working documents as Internet-Drafts. The list of current Internet- 25 Drafts is at https://datatracker.ietf.org/drafts/current/. 27 Internet-Drafts are draft documents valid for a maximum of six months 28 and may be updated, replaced, or obsoleted by other documents at any 29 time. It is inappropriate to use Internet-Drafts as reference 30 material or to cite them other than as "work in progress." 32 This Internet-Draft will expire on February 10, 2020. 34 Copyright Notice 36 Copyright (c) 2019 IETF Trust and the persons identified as the 37 document authors. All rights reserved. 39 This document is subject to BCP 78 and the IETF Trust's Legal 40 Provisions Relating to IETF Documents 41 (https://trustee.ietf.org/license-info) in effect on the date of 42 publication of this document. Please review these documents 43 carefully, as they describe your rights and restrictions with respect 44 to this document. Code Components extracted from this document must 45 include Simplified BSD License text as described in Section 4.e of 46 the Trust Legal Provisions and are provided without warranty as 47 described in the Simplified BSD License. 49 Table of Contents 51 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 52 1.1. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 53 2. Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 54 3. Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . 11 55 3.1. Strict instance semantics . . . . . . . . . . . . . . . . 11 56 3.2. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 12 57 3.3. Forms . . . . . . . . . . . . . . . . . . . . . . . . . . 12 58 3.3.1. Empty . . . . . . . . . . . . . . . . . . . . . . . . 12 59 3.3.2. Ref . . . . . . . . . . . . . . . . . . . . . . . . . 12 60 3.3.3. Type . . . . . . . . . . . . . . . . . . . . . . . . 14 61 3.3.4. Enum . . . . . . . . . . . . . . . . . . . . . . . . 16 62 3.3.5. Elements . . . . . . . . . . . . . . . . . . . . . . 16 63 3.3.6. Properties . . . . . . . . . . . . . . . . . . . . . 17 64 3.3.7. Values . . . . . . . . . . . . . . . . . . . . . . . 19 65 3.3.8. Discriminator . . . . . . . . . . . . . . . . . . . . 20 66 4. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 24 67 5. Security Considerations . . . . . . . . . . . . . . . . . . . 24 68 6. References . . . . . . . . . . . . . . . . . . . . . . . . . 24 69 6.1. Normative References . . . . . . . . . . . . . . . . . . 24 70 6.2. Informative References . . . . . . . . . . . . . . . . . 25 71 Appendix A. Comparison with CDDL . . . . . . . . . . . . . . . . 25 72 Appendix B. Examples . . . . . . . . . . . . . . . . . . . . . . 27 73 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 28 74 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 28 76 1. Introduction 78 This document describes a schema language for JSON [RFC8259] called 79 JSON Schema Language (JSL). 81 The goals of JSL are to: 83 o Provide an unambiguous description of the overall structure of a 84 JSON document. 86 o Be able to describe common JSON datatypes and structures. 88 o Provide a single format that is readable and editable by both 89 humans and machines, and which can be embedded within other JSON 90 documents. 92 o Enable code generation from schemas. 94 o Provide a standardized format for errors when data does not 95 conform with a schema. 97 JSL is intentionally designed as a rather minimal schema language. 98 For example, JSL is homoiconic (it both describes, and is written in, 99 JSON) yet is incapable of describing in detail its own structure. By 100 keeping the expressiveness of the schema language minimal, JSL makes 101 code generation and standardized errors easier to implement. 103 It is expected that for many use-cases, a schema language of JSL's 104 expressiveness is sufficient. Where a more expressive language is 105 required, alternatives exist in CDDL ([RFC8610], Concise Data 106 Definition Language) and others. 108 This document has the following structure: 110 The syntax of JSL is defined in Section 2. Section 3 describes the 111 semantics of JSL; this includes determining whether some data 112 satisfies a schema and what errors should be produced when the data 113 is unsatisfactory. Appendix A presents various JSL schemas and their 114 CDDL equivalents. 116 1.1. Terminology 118 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 119 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 120 "OPTIONAL" in this document are to be interpreted as described in 121 BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all 122 capitals, as shown here. These words may also appear in this 123 document in lower case as plain English words, absent their normative 124 meanings. 126 The term "JSON Pointer", when it appears in this document, is to be 127 understood as it is defined in [RFC6901]. 129 The terms "object", "member", "array", "number", "name", and "string" 130 in this document are to be interpreted as described in [RFC8259]. 132 The term "instance", when it appears in this document, refers to a 133 JSON value being validated against a JSL schema. 135 2. Syntax 137 This section describes when a JSON document is a correct JSL schema. 139 JSL schemas may recursively contain other schemas. In this document, 140 a "root schema" is one which is not contained within another schema, 141 i.e. it is "top level". 143 A correct JSL schema MUST match the "schema" CDDL rule described in 144 this section. A JSL schema is a JSON object taking on an appropriate 145 form. It may optionally contain definitions (a mapping from names to 146 schemas) and additional data. 148 schema = { 149 form, 150 ? definitions: { * tstr => schema }, 151 ? strict: bool, 152 * non-keyword => * 153 } 155 ; This definition prohibits non-keyword from matching any of the 156 ; keywords defined later. 157 non-keyword = 158 (((((((((tstr .ne "definitions") 159 .ne "strict") 160 .ne "ref") 161 .ne "type") 162 .ne "enum") 163 .ne "elements") 164 .ne "properties") 165 .ne "optionalProperties") 166 .ne "values") 167 .ne "discriminator" 169 Figure 1: CDDL Definition of a Schema 171 This is not a correct JSL schema, as its "definitions" object 172 contains a number, which is not a schema: 174 { "definitions": { "foo": 3 }} 176 Here is an example of a valid schema using the "properties", "type", 177 and "ref" forms, which will be described later in this section: 179 { 180 "strict": false, 181 "definitions": { 182 "user": { 183 "properties": { 184 "name": { "type": "string" }, 185 "create_time": { "type": "timestamp" } 186 } 187 } 188 }, 189 "elements": { 190 "ref": "user" 191 } 192 } 193 JSL schemas can take on one of eight forms. These forms are defined 194 so as to be mutually exclusive; a schema cannot satisfy multiple 195 forms at once. 197 form = empty / 198 ref / 199 type / 200 enum / 201 elements / 202 properties / 203 values / 204 discriminator 206 Figure 2: CDDL Definition of the Schema Forms 208 The first form, "empty", is trivial. It is meant for matching any 209 instance: 211 empty = {} 213 Figure 3: CDDL Definition of the Empty Form 215 Thus, this is a correct schema: 217 {} 219 The second form, "ref", is for when a schema is meant to be defined 220 in terms of something in "definitions": 222 ref = { ref: tstr } 224 Figure 4: CDDL Definition of the Ref Form 226 For a schema to be correct, the "ref" value must refer to one of the 227 definitions found at the root level of the schema it appears in. 228 More formally, for a schema _S_ of the "ref" form: 230 o Let _B_ be the root schema containing the schema, or the schema 231 itself if it is a root schema. 233 o Let _R_ be the value of the member of _S_ with the name "ref". 235 If the schema is correct, then _B_ must have a member _D_ with the 236 name "definitions", and _D_ must contain a member whose name equals 237 _R_. 239 Here is a correct example of "ref" being used to avoid re-defining 240 the same thing twice: 242 { 243 "definitions": { 244 "coordinates": { 245 "properties": { 246 "lat": { "type": "number" }, 247 "lng": { "type": "number" } 248 } 249 } 250 }, 251 "properties": { 252 "user_location": { "ref": "coordinates" }, 253 "server_location": { "ref": "coordinates" } 254 } 255 } 257 However, this schema is incorrect, as it refers to a definition that 258 doesn't exist: 260 { 261 "definitions": { "foo": { "type": "number" }}, 262 "ref": "bar" 263 } 265 This schema is incorrect as well, as it refers to a definition that 266 doesn't exist at the root level. The non-root definition is 267 immaterial: 269 { 270 "definitions": { "foo": { "type": "number" }}, 271 "elements": { 272 "definitions": { "bar": { "type": "number" }}, 273 "ref": "bar" 274 } 275 } 277 The third form, "type", constrains instances to have a particular 278 primitive type. The precise meaning of each of the primitive types 279 is described in Section 3. 281 type = { type: "boolean" / num-type / "string" / "timestamp" } 282 num-type = "number" / "float32" / "float64" / 283 "int8" / "uint8" / "int16" / "uint16" / "int32" / "uint32" 285 Figure 5: CDDL Definition of the Type Form 287 For example, this schema constrains instances to be strings that are 288 correct [RFC3339] timestamps: 290 { "type": "timestamp" } 292 The fourth form, "enum", describes instances whose value must be one 293 of a finite, predetermined set of values: 295 enum = { enum: [+ tstr] } 297 Figure 6: CDDL Definition of the Enum Form 299 The values within "[+ tstr]" MUST NOT contain duplicates. Thus, the 300 following is a correct schema: 302 { "enum": ["IN_PROGRESS", "DONE", "CANCELED"] } 304 But this is not a correct schema, as "B" is duplicated: 306 { "enum": ["A", "B", "B"] } 308 The fifth form, "elements", describes instances that must be arrays. 309 A further sub-schema describes the elements of the array. 311 elements = { elements: schema } 313 Figure 7: CDDL Definition of the Elements Form 315 Here is a schema describing an array of [RFC3339] timestamps: 317 { "elements": { "type": "timestamp" }} 319 The sixth form, "properties", describes JSON objects being used as a 320 "struct". A schema of this form specifies the names of required and 321 optional properties, as well as the schemas each of those properties 322 must satisfy: 324 ; One of properties or optionalProperties may be omitted, 325 ; but not both. 326 properties = with-properties / with-optional-properties 328 with-properties = { 329 properties: * tstr => schema, 330 ? optionalProperties * tstr => schema 331 } 333 with-optional-properties = { 334 ? properties: * tstr => schema, 335 optionalProperties: * tstr => schema 336 } 338 Figure 8: CDDL Definition of the Properties Form 340 If a schema has both a member named "properties" (with value _P_) and 341 another member named "optionalProperties" (with value _O_), then _O_ 342 and _P_ MUST NOT have any member names in common. This is to prevent 343 ambiguity as to whether a property is optional or required. 345 Thus, this is not a correct schema, as "confusing" appears in both 346 "properties" and "optionalProperties": 348 { 349 "properties": { "confusing": {} }, 350 "optionalProperties": { "confusing": {} } 351 } 353 Here is a correct schema, describing a paginated list of users: 355 { 356 "properties": { 357 "users": { 358 "elements": { 359 "properties": { 360 "id": { "type": "string" }, 361 "name": { "type": "string" }, 362 "create_time": { "type": "timestamp" } 363 }, 364 "optionalProperties": { 365 "delete_time": { "type": "timestamp" } 366 } 367 } 368 }, 369 "next_page_token": { "type": "string" } 370 } 371 } 372 The seventh form, "values", describes JSON objects being used as an 373 associative array. A schema of this form specifies the form all 374 member values must satisfy, but places no constraints on the member 375 names: 377 values = { values: * tstr => schema } 379 Figure 9: CDDL Definition of the Values Form 381 Thus, this is a correct schema, describing a mapping from strings to 382 numbers: 384 { "values": { "type": "number" }} 386 Finally, the eighth form, "discriminator", describes JSON objects 387 being used as a discriminated union. A schema of this form specifies 388 the "tag" (or "discriminator") of the union, as well as a mapping 389 from tag values to the appropriate schema to use. 391 ; Note well: the values of mapping are of the properties form. 392 discriminator = { tag: tstr, mapping: * tstr => properties } 394 Figure 10: CDDL Definition of the Discriminator Form 396 To prevent ambiguous or unsatisfiable contstraints on the "tag" of a 397 discriminator, an additional constraint on schemas of the 398 discriminator form exists. For schemas of the discriminator form: 400 o Let _D_ be the schema member with the name "discriminator". 402 o Let _T_ be the member of _D_ with the name "tag". 404 o Let _M_ be the member of _D_ with the name "mapping". 406 If the schema is correct, then all member values _S_ of _M_ will be 407 schemas of the "properties" form. For each member _P_ of _S_ whose 408 name equals "properties" or "optionalProperties", _P_'s value, which 409 must be an object, MUST NOT contain any members whose name equals 410 _T_'s value. 412 Thus, this is an incorrect schema, as "event_type" is both the value 413 of "tag" and a member name in one of the "mapping" member 414 "properties": 416 { 417 "tag": "event_type", 418 "mapping": { 419 "is_event_type_a_string_or_a_number?": { 420 "properties": { "event_type": { "type": "number" }} 421 } 422 } 423 } 425 However, this is a correct schema, describing a pattern of data 426 common in JSON-based messaging systems: 428 { 429 "tag": "event_type", 430 "mapping": { 431 "account_deleted": { 432 "properties": { 433 "account_id": { "type": "string" } 434 } 435 }, 436 "account_payment_plan_changed": { 437 "properties": { 438 "account_id": { "type": "string" }, 439 "payment_plan": { "enum": ["FREE", "PAID"] } 440 }, 441 "optionalProperties": { 442 "upgraded_by": { "type": "string" } 443 } 444 } 445 } 446 } 448 This document does not describe any extension mechanisms for JSL 449 schema validation. However, schemas (through the "non-keyword" CDDL 450 rule in this section) are defined to allow members whose names are 451 not equal to any of the specially-defined keywords (i.e. 452 "definitions", "elements", etc.) described in this section. Call 453 these members "non-keyword members". 455 Users MAY add additional, non-keyword members to JSL schemas to 456 convey information that is not pertinent to validation. For example, 457 such non-keyword members could provide hints to code generators, or 458 trigger some special behavior for a library that generates user 459 interfaces from schemas. 461 Users SHOULD NOT expect non-keyword members to be understood by other 462 parties. As a result, if consistent validation with other parties is 463 a requirement, users SHOULD NOT use non-keyword members to affect how 464 schema validation, as described in Section 3, works. 466 3. Semantics 468 This section describes when an instance is valid against a correct 469 JSL schema, and the standardized errors to produce when an instance 470 is invalid. 472 3.1. Strict instance semantics 474 Users will have different desired behavior with respect to 475 "unspcecified" members in an instance. For example: 477 { "properties": { "a": { "type": "string" }}} 479 Some users may expect that {"a": "foo", "b": "bar"} satisfies the 480 above schema. Others may disagree, as "b" is not one of the 481 properties described in the schema. In this document, rejecting such 482 "unspecified" members is called "strict instance semantics". 484 Validation of a schema _S_ uses strict instance semantics if: 486 o Let _R_ be the root schema containing _S_, or _S_ itself if it is 487 a root schema. 489 o Let _M_ be the member of _R_ whose name equals "strict". 491 Validation of a schema _S_ uses strict instance semantics if _M_ does 492 not exist, or if _M_'s value is the JSON boolean "false". 494 By this definition, strict instance semantics is the "default" 495 behavior. Furthermore, as only the "strict" member at the root level 496 determines this strict behavior, it is not possible for a schema to 497 "mix and match" strict and non-strict behavior. 499 See Section 3.3.6 for how strict instance semantics affects schema 500 evaluation, but briefly, the following schema: 502 { "properties": { "a": { "type": "string" }}} 504 Rejects {"a": "foo", "b": "bar"}, but the schema: 506 { 507 "strict": false, 508 "properties": { "a": { "type": "string" }} 509 } 510 Accepts {"a": "foo", "b": "bar"}. 512 3.2. Errors 514 To facilitate consistent validation error handling, this document 515 specifies a standard error format. Implementations SHOULD support 516 producing errors in this standard form. 518 The standard error format is a JSON array. The order of the elements 519 of this array is not specified. The elements of this array are JSON 520 objects with two members: 522 o A member with the name "instancePath", whose value is a JSON 523 string encoding a JSON Pointer. This JSON Pointer will point to 524 the part of the instance that was rejected. 526 o A member with the name "schemaPath", whose value is a JSON string 527 encoding a JSON Pointer. This JSON Pointer will point to the part 528 of the schema that rejected the instance. 530 The values for "instancePath" and "schemaPath" depend on the form of 531 the schema, and are described in detail in Section 3.3. 533 3.3. Forms 535 This section describes, for each of the eight JSL schema forms, the 536 rules dictating whether an instance is accepted, as well as the 537 standardized errors to produce when an instance is invalid. 539 The forms a correct schema may take on are formally described in 540 Section 2. 542 3.3.1. Empty 544 The empty form is meant to describe instances whose values are 545 unknown, unpredictable, or otherwise unconstrained by the schema. 547 If a schema is of the empty form, then it accepts all instances. A 548 schema of the empty form will never produce any errors. 550 3.3.2. Ref 552 The ref form is for when a schema is meant to be defined in terms of 553 something in the "definitions" of the root schema. The ref form 554 enables schemas to be less repetitive, and also enables describing 555 recursive structures. 557 If a schema is of the ref form, then: 559 o Let _B_ be the root schema containing the schema, or the schema 560 itself if it is a root schema. 562 o Let _D_ be the member of _B_ with the name "definitions". By 563 Section 2, _D_ exists. 565 o Let _R_ be the value of the schema member with the name "ref". 567 o Let _S_ be the value of the member of _D_ whose name equals _R_. 568 By Section 2, _S_ exists, and is a schema. 570 The schema accepts the instance if and only if _S_ accepts the 571 instance. Otherwise, the standard errors to return in this case are 572 the union of the errors from evaluating _S_ against the instance. 574 For example, the schema: 576 { 577 "definitions": { "a": { "type": "number" }}, 578 "ref": "a" 579 } 581 Accepts 123 but not false. The standard errors to produce when 582 evaluting false against this schema are: 584 [{ "instancePath": "", "schemaPath": "/definitions/a/type" }] 586 Note that the ref form is defined to only look up definitions at the 587 root level. Thus, with the schema: 589 { 590 "definitions": { "a": { "type": "number" }}, 591 "elements": { 592 "definitions": { "a": { "type": "boolean" }}, 593 "ref": "foo" 594 } 595 } 597 The instance 123 is accepted, and false is rejected. The standard 598 errors to produce when evaluating false against this schema are: 600 [{ "instancePath": "", "schemaPath": "/definitions/a/type" }] 602 Though non-root definitions are not syntactically disallowed in 603 correct schemas, they are entirely immaterial to evaluating 604 references. 606 3.3.3. Type 608 The type form is meant to describe instances whose value is a 609 boolean, number, string, or timestamp ([RFC3339]). 611 If a schema is of the type form, then let _T_ be the value of the 612 member with the name "type". The following table describes whether 613 the instance is accepted, as a function of _T_'s value: 615 +-------------------+----------------------------------------------+ 616 | If _T_ equals ... | then the instance is accepted if it is ... | 617 +-------------------+----------------------------------------------+ 618 | boolean | equal to "true" or "false" | 619 | | | 620 | number | a JSON number | 621 | | | 622 | float32 | a JSON number | 623 | | | 624 | float64 | a JSON number | 625 | | | 626 | int8 | See Table 2 | 627 | | | 628 | uint8 | See Table 2 | 629 | | | 630 | int16 | See Table 2 | 631 | | | 632 | uint16 | See Table 2 | 633 | | | 634 | int32 | See Table 2 | 635 | | | 636 | uint32 | See Table 2 | 637 | | | 638 | string | a JSON string | 639 | | | 640 | timestamp | a JSON string encoding a [RFC3339] timestamp | 641 +-------------------+----------------------------------------------+ 643 Table 1: Accepted Values for Type 645 "float32" and "float64" are distinguished from "number" in their 646 intent. "float32" indicates data intended to be processed as an IEEE 647 754 single-precision float, whereas "float64" indicates data intended 648 to be processed as an IEEE 754 double-precision float. "number" 649 indicates no specific intent. Tools which generate code from JSL 650 schemas will likely produce different code for "float32", "float64", 651 and "number". 653 If _T_ starts with "int" or "uint", then the instance is accepted if 654 and only if it is a JSON number encoding a value with zero fractional 655 part. Depending on the value of _T_, this encoded number must 656 additionally fall within a particular range: 658 +--------+---------------------------+---------------------------+ 659 | _T_ | Minimum Value (Inclusive) | Maximum Value (Inclusive) | 660 +--------+---------------------------+---------------------------+ 661 | int8 | -128 | 127 | 662 | | | | 663 | uint8 | 0 | 255 | 664 | | | | 665 | int16 | -32,768 | 32,767 | 666 | | | | 667 | uint16 | 0 | 65,535 | 668 | | | | 669 | int32 | -2,147,483,648 | 2,147,483,647 | 670 | | | | 671 | uint32 | 0 | 4,294,967,295 | 672 +--------+---------------------------+---------------------------+ 674 Table 2: Ranges for Integer Types 676 Note that 10, 10.0, and 1.0e1 encode values with zero fractional 677 part. 10.5 encodes a number with a non-zero fractional part. Thus 678 {"type": "int8"} accepts 10, 10.0, and 1.0e1, but not 10.5. 680 If the instance is not accepted, then the standard error for this 681 case shall have an "instancePath" pointing to the instance, and a 682 "schemaPath" pointing to the schema member with the name "type". 684 For example: 686 o The schema {"type": "boolean"} accepts false, but rejects 127. 688 o The schema {"type": "number"} accepts 10.5, 127 and 128, but 689 rejects false. 691 o The schema {"type": "int8"} accepts 127, but rejects 10.5, 128 and 692 false. 694 o The schema {"type": "string"} accepts "1985-04-12T23:20:50.52Z" 695 and "foo", but rejects 127. 697 o The schema {"type": "timestamp"} accepts 698 "1985-04-12T23:20:50.52Z", but rejects "foo" and 127. 700 In all of the rejected examples just given, the standard error to 701 produce is: 703 [{ "instancePath": "", "schemaPath": "/type" }] 705 3.3.4. Enum 707 The enum form is meant to describe instances whose value must be one 708 of a finite, predetermined set of string values. 710 If a schema is of the enum form, then let _E_ be the value of the 711 schema member with the name "enum". The instance is accepted if and 712 only if it is equal to one of the elements of _E_. 714 If the instance is not accepted, then the standard error for this 715 case shall have an "instancePath" pointing to the instance, and a 716 "schemaPath" pointing to the schema member with the name "enum". 718 For example, the schema: 720 { "enum": ["PENDING", "DONE", "CANCELED"] } 722 Accepts "PENDING", "DONE", and "CANCELED", but it rejects both 123 723 and "UNKNOWN" with the standard errors: 725 [{ "instancePath": "", "schemaPath": "/enum" }] 727 3.3.5. Elements 729 The elements form is meant to describe instances that must be arrays. 730 A further sub-schema describes the elements of the array. 732 If a schema is of the elements form, then let _S_ be the value of the 733 schema member with the name "elements". The instance is accepted if 734 and only if all of the following are true: 736 o The instance is an array. Otherwise, the standard error for this 737 case shall have an "instancePath" pointing to the instance, and a 738 "schemaPath" pointing to the schema member with the name 739 "elements". 741 o If the instance is an array, then every element of the instance 742 must be accepted by _S_. Otherwise, the standard errors for this 743 case are the union of all the errors arising from evaluating _S_ 744 against elements of the instance. 746 For example, if we have the schema: 748 { 749 "elements": { 750 "type": "number" 751 } 752 } 754 Then the instances [] and [1, 2, 3] are accepted. If instead we 755 evaluate false against that schema, the standard errors are: 757 [{ "instancePath": "", "schemaPath": "/elements" }] 759 Finally, if we evaluate the instance: 761 [1, 2, "foo", 3, "bar"] 763 The standard errors are: 765 [ 766 { "instancePath": "/2", "schemaPath": "/elements/type" }, 767 { "instancePath": "/4", "schemaPath": "/elements/type" } 768 ] 770 3.3.6. Properties 772 The properties form is meant to describe JSON objects being used as a 773 "struct". 775 If a schema is of the properties form, then the instance is accepted 776 if and only if all of the following are true: 778 o The instance is an object. 780 Otherwise, the standard error for this case shall have an 781 "instancePath" pointing to the instance, and a "schemaPath" 782 pointing to the schema member with the name "properties" if such a 783 schema member exists; if such a member doesn't exist, "schemaPath" 784 shall point to the schema member with the name 785 "optionalProperties". 787 o If the instance is an object and the schema has a member named 788 "properties", then let _P_ be the value of the schema member named 789 "properties". _P_, by Section 2, must be an object. For every 790 member name in _P_, a member of the same name in the instance must 791 exist. 793 Otherwise, the standard error for this case shall have an 794 "instancePath" pointing to the instance, and a "schemaPath" 795 pointing to the member of _P_ failing the requirement just 796 described. 798 o If the instance is an object, then let _P_ be the value of the 799 schema member named "properties" (if it exists), and _O_ be the 800 value of the schema member named "optionalProperties" (if it 801 exists). 803 For every member _I_ of the instance, find a member with the same 804 name as _I_'s in _P_ or _O_. By Section 2, it is not possible for 805 both _P_ and _O_ to have such a member. If the "discriminator tag 806 exemption" is in effect on _I_ (see Section 3.3.8), then ignore 807 _I_. Otherwise: 809 * If no such member in _P_ or _O_ exists and validation is using 810 strict instance semantics, then the instance is rejected. 812 The standard error for this case has an "instancePath" pointing 813 _I_, and a "schemaPath" pointing to the schema. 815 * If such a member in _P_ or _O_ does exist, then call this 816 member _S_. If _S_ rejects _I_'s value, then the instance is 817 rejected. 819 The standard error for this case is the union of the errors 820 from evaluating _S_ against _I_'s value. 822 An instance may have multiple errors arising from the second and 823 third bullet in the above. In this case, the standard errors are the 824 union of the errors. 826 For example, if we have the schema: 828 { 829 "properties": { 830 "a": { "type": "string" }, 831 "b": { "type": "string" } 832 }, 833 "optionalProperties": { 834 "c": { "type": "string" }, 835 "d": { "type": "string" } 836 } 837 } 839 Then each of the following instances (one on each line) are accepted: 841 { "a": "foo", "b": "bar" } 842 { "a": "foo", "b": "bar", "c": "baz" } 843 { "a": "foo", "b": "bar", "c": "baz", "d": "quux" } 844 { "a": "foo", "b": "bar", "d": "quux" } 846 If we evaluate the instance 123 against this schema, then the 847 standard errors are: 849 [{ "instancePath": "", "schemaPath": "/properties" }] 851 If instead we evalute the instance: 853 { "b": 3, "c": 3, "e": 3 } 855 The standard errors, using strict instance semantics, are: 857 [ 858 { "instancePath": "", 859 "schemaPath": "/properties/a" }, 860 { "instancePath": "/b", 861 "schemaPath": "/properties/b/type" }, 862 { "instancePath": "/c", 863 "schemaPath": "/optionalProperties/c/type" }, 864 { "instancePath": "/e", 865 "schemaPath": "" } 866 ] 868 If we the same instance were evaluated, but without strict instance 869 semantics, the final element of the above array of errors would not 870 be present. 872 3.3.7. Values 874 The elements form is meant to describe instances that are JSON 875 objects being used as an associative array. 877 If a schema is of the values form, then let _S_ be the value of the 878 schema member with the name "values". The instance is accepted if 879 and only if all of the following are true: 881 o The instance is an object. Otherwise, the standard error for this 882 case shall have an "instancePath" pointing to the instance, and a 883 "schemaPath" pointing to the schema member with the name "values". 885 o If the instance is an object, then every member value of the 886 instance must be accepted by _S_. Otherwise, the standard errors 887 for this case are the union of all the errors arising from 888 evaluating _S_ against member values of the instance. 890 For example, if we have the schema: 892 { 893 "values": { 894 "type": "number" 895 } 896 } 898 Then the instances {} and {"a": 1, "b": 2} are accepted. If instead 899 we evaluate false against that schema, the standard errors are: 901 [{ "instancePath": "", "schemaPath": "/values" }] 903 Finally, if we evaluate the instance: 905 { "a": 1, "b": 2, "c": "foo", "d": 3, "e": "bar" } 907 The standard errors are: 909 [ 910 { "instancePath": "/c", "schemaPath": "/values/type" }, 911 { "instancePath": "/e", "schemaPath": "/values/type" } 912 ] 914 3.3.8. Discriminator 916 The discriminator form is meant to describe JSON objects being used 917 in a fashion similar to a discriminated union construct in C-like 918 languages. When a schema is of the "discriminator" form, it 919 validates: 921 o That the instance is an object, 923 o That the instance has a particular "tag" property, 925 o That this "tag" property's value is a string within a set of valid 926 values, and 928 o That the instance satisfies another schema, where this other 929 schema is chosen based on the value of the "tag" property. 931 The behavior of the discriminator form is more complex than the other 932 keywords. Readers familiar with CDDL may find the final example in 933 Appendix A helpful in understanding its behavior. What follows in 934 this section is a description of the discriminator form's behavior, 935 as well as some examples. 937 If a schema is of the "discriminator" form, then: 939 o Let _D_ be the schema member with the name "discriminator". 941 o Let _T_ be the member of _D_ with the name "tag". 943 o Let _M_ be the member of _D_ with the name "mapping". 945 o Let _I_ be the instance member whose name equals _T_'s value. _I_ 946 may, for some rejected instances, not exist. 948 o Let _S_ be the member of _M_ whose name equals _I_'s value. _S_ 949 may, for some rejected instances, not exist. 951 The instance is accepted if and only if: 953 o The instance is an object. 955 Otherwise, the standard error for this case shall have an 956 "instancePath" pointing to the instance, and a "schemaPath" 957 pointing to _D_. 959 o If the instance is a JSON object, then _I_ must exist. 961 Otherwise, the standard error for this case shall have an 962 "instancePath" pointing to the instance, and a "schemaPath" 963 pointing to _T_. 965 o If the instance is a JSON object and _I_ exists, _I_'s value must 966 be a string. 968 Otherwise, the standard error for this case shall have an 969 "instancePath" pointing to _I_, and a "schemaPath" pointing to 970 _T_. 972 o If the instance is a JSON object and _I_ exists and has a string 973 value, then _S_ must exist. 975 Otherwise, the standard error for this case shall have an 976 "instancePath" pointing to _I_, and a "schemaPath" pointing to 977 _M_. 979 o If the instance is a JSON object, _I_ exists, and _S_ exists, then 980 the instance must satisfy _S_'s value. By Section 2, _S_'s value 981 must have the properties form. Apply the "discriminator tag 982 exemption" afforded in Section 3.3.6 to _I_ when evaluating 983 whether the instance satisfies _S_'s value. 985 Otherwise, the standard errors for this case shall be standard 986 errors from evaluating _S_'s value against the instance, with the 987 "discriminator tag exemption" applied to _I_. 989 Each of the list items above are defined to be mutually exclusive. 990 For the same instance and schema, only one of the list items above 991 will apply. 993 To illustrate the discriminator form, if we have the schema: 995 { 996 "discriminator": { 997 "tag": "version", 998 "mapping": { 999 "v1": { 1000 "properties": { 1001 "a": { "type": "number" } 1002 } 1003 }, 1004 "v2": { 1005 "properties": { 1006 "a": { "type": "string" } 1007 } 1008 } 1009 } 1010 } 1011 } 1013 Then if we evaluate the instance: 1015 "example" 1017 Against this schema, the standard errors are: 1019 [{ "instancePath": "", "schemaPath": "/discriminator" }] 1021 (This is the case of the instance not being an object.) 1023 If we instead evaluate the instance: 1025 {} 1027 Then the standard errors are: 1029 [{ "instancePath": "", "schemaPath": "/discriminator/tag" }] 1031 (This is the case of _I_ not existing.) 1032 If we instead evaluate the instance: 1034 { "version": 1 } 1036 Then the standard errors are: 1038 [{ "instancePath": "/version", "schemaPath": "/discriminator/tag" }] 1040 (This is the case of _I_ existing, but having a string value.) 1042 If we instead evaluate the instance: 1044 { "version": "v3" } 1046 Then the standard errors are: 1048 [ 1049 { "instancePath": "/version", 1050 "schemaPath": "/discriminator/mapping" } 1051 ] 1053 (This is the case of _I_ existing and having a string value, but _S_ 1054 not existing.) 1056 If the instance evaluated were: 1058 { "version": "v2", "a": 3 } 1060 Then the standard errors are: 1062 [ 1063 { 1064 "instancePath": "/a", 1065 "schemaPath": "/discriminator/mapping/v2/properties/a/type" 1066 } 1067 ] 1069 (This is the case of _I_ and _S_ existing, but the instance not 1070 satisfying _S_'s value.) 1072 Finally, if instead the instance were: 1074 { "version": "v2", "a": "foo" } 1076 Then the instance satisfies the schema. No standard errors are 1077 returned. This would be the case even if evaluation were using 1078 strict instance semantics, as the "discriminator tag exemption" would 1079 ensure that "version" is not treated as an unexpected property when 1080 evaluating the instance against _S_'s value. 1082 4. IANA Considerations 1084 No IANA considerations. 1086 5. Security Considerations 1088 Implementations of JSON Schema Language will necessarily be 1089 manipulating JSON data. Therefore, the security considerations of 1090 [RFC8259] are all relevant here. 1092 Implementations which evaluate user-inputted schemas SHOULD implement 1093 mechanisms to detect, and abort, circular references which might 1094 cause a naive implementation to go into an infinite loop. Without 1095 such mechanisms, implementations may be vulnerable to denial-of- 1096 service attacks. 1098 6. References 1100 6.1. Normative References 1102 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 1103 Requirement Levels", BCP 14, RFC 2119, 1104 DOI 10.17487/RFC2119, March 1997, 1105 . 1107 [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: 1108 Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, 1109 . 1111 [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., 1112 "JavaScript Object Notation (JSON) Pointer", RFC 6901, 1113 DOI 10.17487/RFC6901, April 2013, 1114 . 1116 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 1117 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 1118 May 2017, . 1120 [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 1121 Interchange Format", STD 90, RFC 8259, 1122 DOI 10.17487/RFC8259, December 2017, 1123 . 1125 [RFC8610] Birkholz, H., Vigano, C., and C. Bormann, "Concise Data 1126 Definition Language (CDDL): A Notational Convention to 1127 Express Concise Binary Object Representation (CBOR) and 1128 JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610, 1129 June 2019, . 1131 6.2. Informative References 1133 [RFC7071] Borenstein, N. and M. Kucherawy, "A Media Type for 1134 Reputation Interchange", RFC 7071, DOI 10.17487/RFC7071, 1135 November 2013, . 1137 Appendix A. Comparison with CDDL 1139 This appendix is not normative. 1141 To aid the reader familiar with CDDL, this section illustrates how 1142 JSL works by presenting JSL schemas and CDDL schemas which accept and 1143 reject the same instances. 1145 The JSL schema {} accepts the same instances as the CDDL rule: 1147 root = any 1149 The JSL schema: 1151 { 1152 "definitions": { 1153 "a": { "elements": { "ref": "b" }}, 1154 "b": { "type": "number" } 1155 }, 1156 "elements": { 1157 "ref": "a" 1158 } 1159 } 1161 Corresponds to the CDDL schema: 1163 root = [* a] 1165 a = [* b] 1166 b = number 1168 The JSL schema: 1170 { "enum": ["PENDING", "DONE", "CANCELED"]} 1172 Accepts the same instances as the CDDL rule: 1174 root = "PENDING" / "DONE" / "CANCELED" 1176 The JSL schema {"type": "boolean"} corresponds to the CDDL rule: 1178 root = bool 1180 The JSL schema {"type": "number"} corresponds to the CDDL rule: 1182 root = number 1184 The JSL schema {"type": "string"} corresponds to the CDDL rule: 1186 root = tstr 1188 The JSL schema {"type": "timestamp"} corresponds to the CDDL rule: 1190 root = tdate 1192 The JSL schema: 1194 { "elements": { "type": "number" }} 1196 Corresponds to the CDDL rule: 1198 root = [* number] 1200 The JSL schema: 1202 { 1203 "properties": { 1204 "a": { "type": "boolean" }, 1205 "b": { "type": "number" } 1206 }, 1207 "optionalProperties": { 1208 "c": { "type": "string" }, 1209 "d": { "type": "timestamp" } 1210 } 1211 } 1213 Corresponds to the CDDL rule: 1215 root = { a: bool, b: number, ? c: tstr, ? d: tdate } 1217 The JSL schema: 1219 { "values": { "type": "number" }} 1221 Corresponds to the CDDL rule: 1223 root = { * tstr => number } 1225 Finally, the JSL schema: 1227 { 1228 "discriminator": { 1229 "tag": "a", 1230 "mapping": { 1231 "foo": { 1232 "properties": { 1233 "b": { "type": "number" } 1234 } 1235 }, 1236 "bar": { 1237 "properties": { 1238 "b": { "type": "string" } 1239 } 1240 } 1241 } 1242 } 1243 } 1245 Corresponds to the CDDL rule: 1247 root = { a: "foo", b: number } / { a: "bar", b: tstr } 1249 Appendix B. Examples 1251 This appendix is not normative. 1253 As a demonstration of JSL, here is a JSL schema closely equivalent to 1254 the plain-English definition "reputation-object" described in 1255 Section 6.2.2 of [RFC7071]: 1257 { 1258 "properties": { 1259 "application": { "type": "string" }, 1260 "reputons": { 1261 "elements": { 1262 "properties": { 1263 "rater": { "type": "string" }, 1264 "assertion": { "type": "string" }, 1265 "rated": { "type": "string" }, 1266 "rating": { "type": "float32" }, 1267 }, 1268 "optionalProperties": { 1269 "confidence": { "type": "float32" }, 1270 "normal-rating": { "type": "float32" }, 1271 "sample-size": { "type": "uint32" }, 1272 "generated": { "type": "uint32" }, 1273 "expires": { "type": "uint32" } 1274 } 1275 } 1276 } 1277 } 1278 } 1280 This schema does not support "ext-value", and limits "generated" and 1281 "expires" to timestamps less than 2^32 seconds after January 1, 1970 1282 00:00 UTC. It does not express the limitation that "rating", 1283 "confidence", and "normal-rating" should not have more than three 1284 decimal places of precision. 1286 This can be compared against the equivalent example in Appendix H of 1287 [RFC8610]. 1289 Acknowledgments 1291 Thanks to Gary Court, Francis Galiegue, Kris Zyp, Geraint Luff, Jason 1292 Desrosiers, Daniel Perrett, Erik Wilde, Ben Hutton, Evgeny 1293 Poberezkin, Brad Bowman, Gowry Sankar, Donald Pipowitch, Dave Finlay, 1294 Denis Laxalde, Henry Andrews, and Austin Wright for their work on the 1295 initial drafts of JSON Schema, which inspired JSON Schema Language. 1297 Thanks to Tim Bray, Carsten Bormann, and James Manger for their help 1298 on JSON Schema Language. 1300 Author's Address 1302 Ulysse Carion 1304 Email: ulyssecarion@gmail.com