idnits 2.17.1 draft-newton-json-content-rules-08.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 document seems to lack a Security Considerations section. ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) == There are 1 instance of lines with non-RFC2606-compliant FQDNs in the document. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (March 28, 2017) is 2558 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. 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: '116' on line 238 -- Looks like a reference, but probably isn't: '943' on line 238 -- Looks like a reference, but probably isn't: '234' on line 238 -- Looks like a reference, but probably isn't: '38793' on line 238 == Missing Reference: 'I-D.cordell-jcr-co-constraints' is mentioned on line 1707, but not defined ** Downref: Normative reference to an Informational RFC: RFC 1166 ** Obsolete normative reference: RFC 4234 (Obsoleted by RFC 5234) ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) Summary: 5 errors (**), 0 flaws (~~), 3 warnings (==), 6 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group A. Newton 3 Internet-Draft ARIN 4 Intended status: Standards Track P. Cordell 5 Expires: September 29, 2017 Codalogic 6 March 28, 2017 8 A Language for Rules Describing JSON Content 9 draft-newton-json-content-rules-08 11 Abstract 13 This document describes a language for specifying and testing the 14 expected content of JSON structures found in JSON-using protocols, 15 software, and processes. 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 http://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 September 29, 2017. 34 Copyright Notice 36 Copyright (c) 2017 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 (http://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 . . . . . . . . . . . . . . . . . . . . . . . . 3 52 1.1. A First Example: Specifying Content . . . . . . . . . . . 3 53 1.2. A Second Example: Testing Content . . . . . . . . . . . . 3 54 2. Overview of the Language . . . . . . . . . . . . . . . . . . 5 55 3. Lines and Comments . . . . . . . . . . . . . . . . . . . . . 7 56 4. Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 57 4.1. Rule Names and Assignments . . . . . . . . . . . . . . . 8 58 4.2. Annotations . . . . . . . . . . . . . . . . . . . . . . . 9 59 4.3. Starting Points and Root Rules . . . . . . . . . . . . . 10 60 4.4. Type Specifications . . . . . . . . . . . . . . . . . . . 10 61 4.5. Primitive Specifications . . . . . . . . . . . . . . . . 12 62 4.5.1. Numbers, Booleans and Null . . . . . . . . . . . . . 12 63 4.5.2. Strings . . . . . . . . . . . . . . . . . . . . . . . 13 64 4.6. Any Type . . . . . . . . . . . . . . . . . . . . . . . . 16 65 4.7. Member Specifications . . . . . . . . . . . . . . . . . . 16 66 4.8. Object Specifications . . . . . . . . . . . . . . . . . . 16 67 4.9. Array Specifications . . . . . . . . . . . . . . . . . . 19 68 4.9.1. Unordered Array Specifications . . . . . . . . . . . 21 69 4.10. Group Specifications . . . . . . . . . . . . . . . . . . 21 70 4.11. Ordered and Unordered Groups in Arrays . . . . . . . . . 22 71 4.12. Sequence and Choice Combinations in Array, Object, and 72 Group Specifications . . . . . . . . . . . . . . . . . . 22 73 4.13. Repetition in Array, Object, and Group Specifications . . 23 74 4.14. Negating Evaluation . . . . . . . . . . . . . . . . . . . 25 75 5. Directives . . . . . . . . . . . . . . . . . . . . . . . . . 26 76 5.1. jcr-version . . . . . . . . . . . . . . . . . . . . . . . 26 77 5.2. ruleset-id . . . . . . . . . . . . . . . . . . . . . . . 27 78 5.3. import . . . . . . . . . . . . . . . . . . . . . . . . . 27 79 6. Tips and Tricks . . . . . . . . . . . . . . . . . . . . . . . 28 80 6.1. Any Member with Any Value . . . . . . . . . . . . . . . . 28 81 6.2. Lists of Values . . . . . . . . . . . . . . . . . . . . . 29 82 6.3. Groups in Arrays . . . . . . . . . . . . . . . . . . . . 29 83 6.4. Groups in Objects . . . . . . . . . . . . . . . . . . . . 30 84 6.5. Group Rules as Macros . . . . . . . . . . . . . . . . . . 31 85 6.6. Object Mixins . . . . . . . . . . . . . . . . . . . . . . 31 86 6.7. Subordinate Dependencies . . . . . . . . . . . . . . . . 31 87 7. ABNF Syntax . . . . . . . . . . . . . . . . . . . . . . . . . 32 88 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 38 89 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 38 90 9.1. Normative References . . . . . . . . . . . . . . . . . . 38 91 9.2. Infomative References . . . . . . . . . . . . . . . . . . 38 92 Appendix A. Co-Constraints . . . . . . . . . . . . . . . . . . . 39 93 Appendix B. Testing Against JSON Content Rules . . . . . . . . . 39 94 B.1. Locally Overriding Rules . . . . . . . . . . . . . . . . 39 95 B.2. Rule Callbacks . . . . . . . . . . . . . . . . . . . . . 40 96 Appendix C. JCR Implementations . . . . . . . . . . . . . . . . 40 97 Appendix D. Syntax Changes from -06 and -07 . . . . . . . . . . 41 98 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 41 100 1. Introduction 102 This document describes JSON Content Rules (JCR), a language for 103 specifying and testing the interchange of data in JSON [RFC7159] 104 format used by computer protocols and processes. The syntax of JCR 105 is not JSON but is "JSON-like", possessing the conciseness and 106 utility that has made JSON popular. 108 1.1. A First Example: Specifying Content 110 The following JSON data describes a JSON object with two members, 111 "line-count" and "word-count", each containing an integer. 113 { "line-count" : 3426, "word-count" : 27886 } 115 Figure 1 117 This is also JCR that describes a JSON object with a member named 118 "line-count" that is an integer that is exactly 3426 and a member 119 named "word-count" that is an integer that is exactly 27886. 121 For a protocol specification, it is probably more useful to specify 122 that each member is any integer and not specific, exact integers: 124 { "line-count" : integer, "word-count" : integer } 126 Figure 2 128 Since line counts and word counts should be either zero or a positive 129 integer, the specification may be further narrowed: 131 { "line-count" : 0.. , "word-count" : 0.. } 133 Figure 3 135 1.2. A Second Example: Testing Content 137 Building on the first example, this second example describes the same 138 object but with the addition of another member, "file-name". 140 { 141 "file-name" : "rfc7159.txt", 142 "line-count" : 3426, 143 "word-count" : 27886 144 } 146 Figure 4 148 The following JCR describes objects like it. 150 { 151 "file-name" : string, 152 "line-count" : 0.., 153 "word-count" : 0.. 154 } 156 Figure 5 158 For the purposes of writing a protocol specification, JCR may be 159 broken down into named rules to reduce complexity and to enable re- 160 use. The following example takes the JCR from above and rewrites the 161 members as named rules. 163 { 164 $fn, 165 $lc, 166 $wc 167 } 169 $fn = "file-name" : string 170 $lc = "line-count" : 0.. 171 $wc = "word-count" : 0.. 173 Figure 6 175 With each member specified as a named rule, software testers can 176 override them locally for specific test cases. In the following 177 example, the named rules are locally overridden for the test case 178 where the file name is "rfc4627.txt". 180 $fn = "file-name" : "rfc4627.txt" 181 $lc = "line-count" : 2102 182 $wc = "word-count" : 16714 184 Figure 7 186 In this example, the protocol specification describes the JSON object 187 in general and an implementation overrides the rules for testing 188 specific cases. 190 2. Overview of the Language 192 JCR is composed of rules (as the name suggests). A collection of 193 rules that is processed together is a ruleset. Rulesets may also 194 contain comments, blank lines, and directives that apply to the 195 processing of a ruleset. 197 Rules are composed of two parts, an optional rule name and a rule 198 specification. A rule specification can be either a type 199 specification or a member specification. A member specification 200 consists of a member name specification and a type specification. 202 A type specification is used to specify constraints on a superset of 203 a JSON value (e.g. number / string / object / array etc.). In 204 addition to defining primitive types (such as string or integer), 205 array types, and object types, type specifications may define the JCR 206 specific concept of group types. 208 Type specifications corresponding to arrays, objects and groups may 209 be composed of other rule specifications. 211 A member specification is used to specify constraints on a JSON 212 member (i.e. members of a JSON object). 214 Rules with rule name assignments may be referenced in place of type 215 specifications and member specifications. 217 Rules may be defined across line boundaries and there is no line 218 continuation syntax. 220 Any rule consisting only of a type specification is considered a root 221 rule. Unless otherwise specified, all the root rules of a ruleset 222 are evaluated against a JSON instance or document. 224 Putting it all together, Figure 9 describes the JSON in Figure 8. 226 Example JSON shamelessly lifted from RFC 4627 228 { 229 "Image": { 230 "Width": 800, 231 "Height": 600, 232 "Title": "View from 15th Floor", 233 "Thumbnail": { 234 "Url": "http://www.example.com/image/481989943", 235 "Height": 125, 236 "Width": 100 237 }, 238 "IDs": [116, 943, 234, 38793] 239 } 240 } 242 Figure 8 244 Rules describing Figure 8 246 ; the root of the JSON instance is an object 247 ; this root rule describes that object 248 { 250 ; the object specification contains 251 ; one member specification 252 "Image" : { 254 ; $width and $height are defined below 255 $width, 256 $height, 258 ; "Title" member specification 259 "Title" :string, 261 ; "Thumbnail" member specification, which 262 ; defines an object 263 "Thumbnail": { 265 ; $width and $height are re-used again 266 $width, $height, 268 "Url" :uri 269 }, 271 ; "IDs" member that is an array of 272 ; one ore more integers 273 "IDs" : [ integer * ] 275 } 276 } 278 ; The definitions of the rules $width and $height 279 $width = "Width" : 0..1280 280 $height = "Height" : 0..1024 282 Figure 9 284 3. Lines and Comments 286 There is no statement terminator and therefore no need for a line 287 continuation syntax. Rules may be defined across line boundaries. 288 Blank lines are allowed. 290 Comments are the same as comments in ABNF [RFC4234]. They start with 291 a semi-colon (';') and continue to the end of the line. 293 4. Rules 295 Rules have two main components, an optional rule name assignment and 296 a type or member specification. 298 Type specifications define arrays, objects, etc... of JSON and may 299 reference other rules using rule names. Most type specifications can 300 be defined with repetitions for specifying the frequency of the type 301 being defined. In addition to the type specifications describing 302 JSON types, there is an additional group specification for grouping 303 types. 305 Member specifications define members of JSON objects, and are 306 composed of a member name specification and either a type 307 specification or a rule name referencing a type specification. 309 Rules may also contain annotations which may affect the evaluation of 310 all or part of a rule. Rules without a rule name assignment are 311 considered root rules, though rules with a rule name assignment can 312 be considered a root rule with the appropriate annotation. 314 Type specifications, depending on their type, can contain zero or 315 more other specifications or rule names. For example, an object 316 specification might contain multiple member specifications or rule 317 names that resolve to member specifications or a mixture of member 318 specifications and rule names. For the purposes of this document, 319 specifications and rule names composing other specifications are 320 called subordinate components. 322 4.1. Rule Names and Assignments 324 Rule names are signified with the dollar character ('$'), which is 325 not part of the rule name itself. Rule names have two components, an 326 optional ruleset identifier alias and a local rule name. 328 Local rule names must start with an alphabetic character (a-z,A-Z) 329 and must contain only alphabetic characters, numeric characters, the 330 hyphen character ('-') and the underscore character ('_'). Local 331 rule names are case sensitive, and must be unique within a ruleset 332 (that is, no two rule name assignments may use the same local rule 333 name). 335 Ruleset identifier aliases enable referencing rules from another 336 ruleset. They are not allowed in rule name assignments, and only 337 found in rule names referencing other rules. Ruleset identifiers 338 must start with an alphabetic character and contain no whitespace. 339 Ruleset identifiers are case sensitive. Simple use cases of JCR will 340 most likely not use ruleset identifiers. 342 In Figure 10 below, "http://ietf.org/rfcYYYY.JCR" and 343 "http://ietf.org/rfcXXXX.JCR" are ruleset identifiers and "rfcXXXX" 344 is a ruleset identifier alias. 346 # ruleset-id http://ietf.org/rfcYYYY.JCR 347 # import http://ietf.org/rfcXXXX.JCR as rfcXXXX 348 $my_encodings = ( "mythic" | "magic" ) 349 $all_encodings = ( $rfcXXXX.encodings | $my_encodings ) 351 Figure 10 353 There are two forms of rule name assignments: assignments of 354 primitive types and assignments of all other types. Rule name 355 assignments to primitive type specifications separate the rule name 356 from the type specification with the character sequence '=:', whereas 357 rule name assignments for all other type specifications only require 358 the separation using the '=' character. 360 ;rule name assignments for primitive types 361 $foo =: "foo" 362 $some_string =: string 364 ;rule name assignments for arrays 365 $bar = [ integer, integer, integer ] 367 ;rule name assignement for objects 368 $bob = { "bar" : $bar, "foo" : $foo } 370 Figure 11 372 This is the one little "gotcha" in JCR. This syntax is necessary so 373 that JCR parsers may readily distinguish between rule name 374 assignments involving string and regular expressions primitive types 375 and member names of member specifications. 377 4.2. Annotations 379 Annotations may appear before a rule name assignment, before a type 380 or member specification, or before a rule name contained within a 381 type specification. In each place, there may be zero or more 382 annotations. Each annotation begins with the character sequence "@{" 383 and ends with "}". The following is an example of a type 384 specification with the not annotation (explained in Section 4.14): 386 @{not} [ "fruits", "vegatables" ] 388 Figure 12 390 This specification defines the annotations "root", "not", and 391 "unordered", but other annotations may be defined for other purposes. 393 4.3. Starting Points and Root Rules 395 Evaluation of a JSON instance or document against a ruleset begins 396 with the evaluation of a root rule or set of root rules. If no root 397 rule (or rules) is specified locally at runtime, the set of root 398 rules specified in the ruleset are evaluated. The order of 399 evaluation is undefined. 401 The set of root rules specified in a ruleset is composed of all rules 402 without a rule name assignment and all rules annotated with the 403 "@{root}" annotation. 405 The "@{root}" annotation may either appear before a rule name 406 assignment or before a type definition. It is ignored if present 407 before referenced rule name inside of a type specification. 409 4.4. Type Specifications 411 The syntax of each type of type specifications varies depending on 412 the type: 414 ; primitive types can be string 415 ; or number literals 416 ; or number ranges 417 "foo" 418 2 419 1..10 421 ; primitive types can also be more generalized types 422 string 423 integer 425 ; primitive type rules may be named 426 $my_int =: 12 428 ; member specifications consist of a member name 429 ; followed by a colon and then followed by another 430 ; type specification or a rule name 431 ; (example shown with a rule name assignment) 432 $mem1 = "bar" : "baz" 433 $mem2 = "fizz" : $my_int 435 ; member names may either be quoted strings 436 ; or regular expressions 437 ; (example shown with a rule name assignment) 438 $mem3 = /^dev[0-9]$/ : 0..4096 440 ; object specifications start and end with "curly braces" 441 ; object specifications contain zero 442 ; or more member specifications 443 ; or rule names which reference a member specification 444 { $mem1, "foo" : "fuzz", "fizz" : $my_int } 446 ; array specifications start and end with square brackets 447 ; array specifications contain zero 448 ; or more non-member type specifications 449 [ 1, 2, 3, $my_int ] 451 ; finally, group specifications start and end with parenthesis 452 ; groups contain other type specifications 453 ( [ integer, integer], $rule1 ) 454 $rule1 = [ string, string ] 456 Figure 13 458 4.5. Primitive Specifications 460 Primitive type specifications define content for JSON numbers, 461 booleans, strings, and null. 463 4.5.1. Numbers, Booleans and Null 465 The rules for booleans and null are the simplest and take the 466 following forms: 468 true 469 false 470 boolean 471 null 473 Figure 14 475 Rules for numbers can specify the number be either an integer or 476 floating point number: 478 integer 479 float 480 double 482 Figure 15 484 The keyword 'float' represents a single precision IEEE-754 floating 485 point number represented in decimal. The keyword 'double' represents 486 a double precision IEEE-754 floating point number represented in 487 decimal format. 489 Numbers may also be specified as an absolute value or a range of 490 possible values, where a range may be specified using a minimum, 491 maximum, or both: 493 n 494 n..m 495 ..m 496 n.. 497 n.f 498 n.f..m.f 499 ..m.f 500 n.f.. 502 Figure 16 504 When specifying a minimum and a maximum, both must either be an 505 integer or a floating point number. Thus to specify a floating point 506 number between zero and ten a definition of the following form is 507 used: 509 0.0..10.0 511 Figure 17 513 Integers may also be specified as ranges using bit lengths preceded 514 by the 'int' or 'uint' words (i.e. 'int8', 'uint16'). The 'int' 515 prefix specifies the integer as being signed whereas the 'uint' 516 prefix specifies the integer as being unsigned. 518 ; 0..255 519 uint8 521 ; -32768..32767 522 int16 524 ; 0..65535 525 uint16 527 ; -9223372036854775808..9223372036854775807 528 int64 530 ; 0..18446744073709551615 531 uint64 533 Figure 18 535 4.5.2. Strings 537 JCR provides a large number of data types to define the contents of 538 JSON strings. Generically, a string may be specified using the word 539 'string'. String literals may be specified using a double quote 540 character followed by the literal content followed by another double 541 quote. And regular expressions may be specified by enclosing a 542 regular expression within the forward slash ('/') character. 544 ; any string 545 string 547 ; a string literal 548 "she sells sea shells" 550 ; a regular expression 551 /^she sells .*/ 553 Figure 19 555 Regular expressions are not implicitly anchored and therefore must be 556 explicitly anchored if necessary. 558 A string can be specified as a URI [RFC3986] using the word 'uri', 559 but also may be more narrowly scoped to a URI of a specific scheme. 560 Specific URI schemes are specified with the word 'uri' followed by 561 two period characters ('..') followed by the URI scheme. 563 ; any URI 564 uri 566 ;a URI narrowed for an HTTPS uri 567 uri..https 569 Figure 20 571 IP addresses may be specified with either the word 'ipv4' for IPv4 572 addresses [RFC1166] or the word 'ipv6' for IPv6 addresses [RFC5952]. 573 Fully qualified A-label and U-label domain names may be specified 574 with the words 'fqdn' and 'idn'. 576 Dates and time can be specified as formats found in RFC 3339 577 [RFC3339]. The word 'date' corresponds to the full-date ABNF rule, 578 the word 'time' corresponds to the full-time ABNF rule, and the word 579 'datetime' corresponds to the 'date-time' ABNF rule. 581 Email addresses formatted according to RFC 5322 [RFC5322] may be 582 specified using the 'email' word, and E.123 phone numbers may be 583 specified using the word 'phone'. 585 ;IP addresses 586 ipv4 587 ipv6 588 ipaddr 590 ;domain names 591 fqdn 592 idn 594 ; RFC 3339 full-date 595 date 596 ; RFC 3339 full-time 597 time 598 ; RFC 3339 date-time 599 datetime 601 ; RFC 5322 email address 602 email 604 ; phone number 605 phone 607 Figure 21 609 Binary data can be specified in string form using the encodings 610 specified in RFC 4648 [RFC4648]. The word 'hex' corresponds to 611 base16, while 'base32', 'base32hex', 'base64', and 'base64url' 612 correspond with their RFC 4648 counterparts accordingly. 614 ; RFC 4648 base16 615 hex 617 ; RFC 4648 base32 618 base32 620 ; RFC 4648 base32hex 621 base32hex 623 ; RFC 4648 base64 624 base64 626 ; RFC 4648 base64url 627 base64url 629 Figure 22 631 4.6. Any Type 633 It is possible to specify that a value can be of any type allowable 634 by JSON using the word 'any'. The 'any' type specifies any primitive 635 type, array, or object. 637 4.7. Member Specifications 639 Member specifications define members of JSON objects. Unlike other 640 type specifications, member specifications cannot be root rules and 641 must be part of an object specification or preceded by a rule name 642 assignment. 644 Member specifications consist of a member name specification followed 645 by a colon character (':') followed by either a subordinate 646 component, which is either a rule name or a primitive, object, array, 647 or group specification. Member name specifications can be given 648 either as a quoted string using double quotes or as a regular 649 expression using forward slash ('/') characters. Regular expressions 650 are not implicitly anchored and therefore must have explicit anchors 651 if needed. 653 ;member name will exactly match "locationURI" 654 $location_uri = "locationURI" : uri 656 ;member name will match "eth0", "eth1", ... "eth9" 657 $iface_mappings = /^eth[0-9]$/ : ipv4 659 Figure 23 661 4.8. Object Specifications 663 Object specifications define JSON objects and are composed of zero or 664 more subordinate components, each of which can be either a rule name, 665 member specification, or group specification. The subordinate 666 components are enclosed at the start with a left curly brace 667 character ('{') and at the end with a right curly brace character 668 ('}'). 670 Evaluation of the subordinate components of object specifications is 671 as follows: 673 o No order is implied for the members of the object being evaluated. 675 o Subordinate components of the object specification are evaluated 676 in the order they appear. 678 o Each member of the object being evaluated can only match one 679 subordinate component. 681 o Any members not matched against a subordinate component are 682 ignored. 684 The following examples illustrate matching of JSON objects to JCR 685 object specifications. 687 As order is not implied for the members of objects under evaluation, 688 the following rule will match the JSON in Figure 25 and Figure 26. 690 { "locationUri" : uri, "statusCode" : integer } 692 Figure 24 694 { "locationUri" : "http://example.com", "statusCode" : 200 } 696 Figure 25 698 { "statusCode" : 200, "locationUri" : "http://example.com" } 700 Figure 26 702 Because subordinate components of an object specification are 703 evaluated in the order in which they are specified (i.e. left to 704 right, top to bottom) and object members can only match one 705 subordinate component of an object specification, the rule o1 below 706 will not match against the JSON in Figure 28 but the rule o2 below 707 will match it. 709 ; zero or more members that match "p0", "p1", etc 710 ; and a member that matches "p1" 711 $o1 = { /^p\d+$/ : integer *, "p1" : integer } 713 ; a member that matches "p1" and 714 ; zero or more members that match "p0", "p1", etc 715 $o2 = { "p1" : integer, /^p\d+$/ : integer * } 717 The first subordinate of rule o1 specifies that an object can have 718 zero or more members (that is the meaning of "*", see Section 4.13) 719 where the member name is the letter 'p' followed by a number (e.g. 720 "p0", "p1", "p2"), and the second rule specifies a member with the 721 exact member name of "p1". Rule o2 has the exact same member 722 specifications but in the opposite order. Figure 28 does not match 723 rule o1 because all of the members match the first subordinate rule 724 leaving none to match the second subordinate rule. However, rule o2 725 does match because the first subordinate rule matches only one member 726 of the JSON object allowing the second subordinate rule to match the 727 other member of the JSON object. 729 Figure 27 731 { "p0" : 1, "p1" : 2 } 733 Figure 28 735 As stated above, members of objects which do not match a rule are 736 ignored. The reason for this validation model is due to the nature 737 of the typical access model to JSON objects in many programming 738 languages, where members of the object are obtained by referencing 739 the member name. Therefore extra members may exist without harm. 741 However, some specifications may need to restrict the members of a 742 JSON object to a known set. To construct a rule specifying that no 743 extra members are expected, the @{not} annotation (see Section 4.14) 744 may be used with a "match-all" regular expression as the last 745 subordinate component of the object specification. 747 The following rule will match the JSON object in Figure 30 but will 748 not match the JSON object in Figure 31. 750 { "foo" : 1, "bar" : 2, @{not} // : any + } 752 Figure 29 754 { "foo" : 1, "bar" : 2 } 756 Figure 30 758 { "foo" : 1, "bar" : 2, "baz" : 3 } 760 Figure 31 762 This works because subordinate components are evaluated in the order 763 they appear in the object rule, and the last component accepts any 764 member with any type but fails to validate if one or more of those 765 components are found due to the @{not} annotation. 767 4.9. Array Specifications 769 Array specifications define JSON arrays and are composed of zero or 770 more subordinate components, each of which can either be a rule name 771 or a primitive, array, object or group specification. The 772 subordinate components are enclosed at the start with a left square 773 brace character ('[') and at the end with a right square brace 774 character (']'). 776 Evaluation of the subordinate components of array specifications is 777 as follows: 779 o The order of array items is implied unless the @{unordered} 780 annotation is present. 782 o Subordinate components of the array specification are evaluated in 783 the order they appear. 785 o Each item of the array being evaluated can only match one 786 subordinate component of the array specification. 788 o If any items of the array are not matched, then the array does not 789 match the array specification. 791 These rules are further explained in the examples below. 793 [ 0..1024, 0..980 ] 795 Figure 32 797 Unlike object specifications, order is implied in array 798 specifications by default. That is, the first subordinate component 799 will match the first element of the array, the second subordinate 800 component will match the second element of the array, and so on. 802 Take for example the following ruleset: 804 ; the first element of the array is to be a string 805 ; the second element of the array is to be an integer 806 $a1 = [ string, integer ] 808 ; the first element of the array is to be an integer 809 ; the second element of the array is to be a string 810 $a2 = [ integer, string ] 812 Figure 33 814 It defines two rules, a1 and a2. The array in the following JSON 815 will not match a1, but will match a2. 817 [ 24, "Bob Smurd" ] 819 Figure 34 821 If an array has more elements than can be matched from the array 822 specification, the array does not match the array specification. Or 823 stated differently, an array with unmatched elements does not 824 validate. Using the example array rule a2 from above, the following 825 array does not match because the last element of the array does not 826 match any subordinate component: 828 [ 24, "Bob Smurd", "http://example.com/bob_smurd" ] 830 Figure 35 832 To allow an array to contain any value after guaranteeing that it 833 contains the necessary items, the last subordinate component of the 834 array specification should accept any item: 836 ; the first element of the array is to be an integer 837 ; the second element of the array is to be a string 838 ; anything else can follow 839 $a3 = [ integer, string, any * ] 841 The JSON array in Figure 35 will validate against the a3 rule in this 842 example. 844 Figure 36 846 4.9.1. Unordered Array Specifications 848 Array specifications can be made to behave in a similar fashion to 849 object specifications with regard to the order of matching with the 850 @{unordered} annotation. 852 In the ruleset below, a1 and a2 have the same subordinate components 853 given in the same order. a2 is annotated with the @{unordered} 854 annotation. 856 $a1 = [ string, integer ] 857 $a2 = @{unordered} [ string, integer ] 859 Figure 37 861 The JSON array below does not match a1 but does match a2. 863 [ 24, "Bob Smurd" ] 865 Figure 38 867 Like ordered array specifications, the subordinate components in an 868 unordered array specification are evaluated in the order they are 869 specified. The difference is that they need not match an element of 870 the array in the same position as given in the array specification. 872 Finally, like ordered array specifications, unordered array 873 specifications also require that all elements of the array be matched 874 by a subordinate component. If the array has more elements than can 875 be matched, the array does not match the array specification. 877 4.10. Group Specifications 879 Unlike the other type specifications, group specifications have no 880 direct tie with JSON syntax. Group specifications simply group 881 together their subordinate components. Group specifications enclose 882 one or more subordinate components with the parenthesis characters. 884 Group specifications and any nesting of group specifications, must 885 conform to the allowable set of type specifications of the type 886 specifications in which they are contained. For example, a group 887 specification inside of an array specification may not contain a 888 member specification since member specifications are not allowed as 889 direct subordinates of array specifications (arrays contain values, 890 not object members in JSON). Likewise, a group specification 891 referenced inside an object specification must only contain member 892 specifications (JSON objects may only contain object members). 894 The following is an example of a group specification: 896 $the_bradys = [ $parents, $children ] 898 $children = ( "Greg", "Marsha", "Bobby", "Jan" ) 900 $parents = ( "Mike", "Carol" ) 902 Figure 39 904 Like the subordinate components of array and object specifications, 905 the subordinate components of a group specification are evaluated in 906 the order they appear. 908 4.11. Ordered and Unordered Groups in Arrays 910 Section 4.9.1 specifies that arrays can be evaluated by the order of 911 the items in the array or can be evaluated without order. 912 Section 4.10 specifies that arrays may have group rules as 913 subordinate components. 915 The evaluation of a group specification inside an array specification 916 inherits the ordering property of the array specification. If the 917 array specification is unordered, then the items of the group 918 specification are also considered to be unordered. And if the array 919 specification is ordered, then the items of the group specification 920 are also considered to be ordered. 922 4.12. Sequence and Choice Combinations in Array, Object, and Group 923 Specifications 925 Combinations of subordinate components in array, object, and group 926 specifications can be specified as either a sequence ("and") or a 927 choice ("or"). A sequence is a subordinate component followed by the 928 comma character (',') followed by another subordinate component. A 929 choice is a subordinate component followed by a pipe character ('|') 930 followed by another subordinate component. 932 ; sequence ("and") 933 [ "this" , "that" ] 935 ; choice ("or") 936 [ "this" | "that" ] 938 Figure 40 940 Sequence and choice combinations cannot be mixed, and group 941 specifications must be used to explicitly declare precedence between 942 a sequence and a choice. Therefore, the following is illegal: 944 [ "this", "that" | "the_other" ] 946 Figure 41 948 The example above should be expressed as: 950 [ "this", ( "that" | "the_other" ) ] 952 Figure 42 954 NOTE: A future specification will clarify the choice ('|') 955 operation as inclusive or, exclusive or ("xor") or otherwise. At 956 present readers should assume the choice ('|') operator is an 957 inclusive or. However, for objects and unordered arrays that is 958 not ideal, nor is xor. We are in the process of defining an 959 algorithm to "rewrite" choices of rules for use with inclusive or 960 which is more suitable for the data model of JSON. 962 4.13. Repetition in Array, Object, and Group Specifications 964 Evaluation of subordinate components in array, object, and group 965 specifications may be succeeded by a repetition expression denoting 966 how many times the subordinate component should be evaluated. 967 Repetition expressions are specified using a Kleene symbol ('?', '+', 968 or '*') or with the '*' symbol succeeded by specific minimum and/or 969 maximum values, each being non-negative integers. Repetition 970 expressions may also be appended with a step expression, which is the 971 '%' symbol followed by a positive integer. 973 When no repetition expression is present, both the minimum and 974 maximum are 1. 976 A minimum and maximum can be expressed by giving the minimum followed 977 by two period characters ('..') followed by the maximum, with either 978 the minimum or maximum being optional. When the minimum is not 979 explicitly specified, it is assumed to be zero. When the maximum is 980 not explicitly specified, it is assumed to be positive infinity. 982 ; exactly 2 octets 983 $word = [ $octet *2 ] 984 $octet =: int8 986 ; 1 to 13 name servers 987 [ $name_servers *1..13 ] 988 $name_servers =: fqdn 990 ; 0 to 99 ethernet addresses 991 { /^eth.*/ : $mac_addr *..99 } 992 $mac_addr =: hex 994 ; four or more bytes 995 [ $octet *4.. ] 997 Figure 43 999 The allowable Kleene operators are the question mark character ('?') 1000 which specifies zero or one (i.e. optional), the plus character ('+') 1001 which specifies one or more, and the asterisk character ('*') which 1002 specifies zero or more. 1004 ; age is optional 1005 { "name" : string, "age" : integer ? } 1007 ; zero or more errors 1008 $error_set = ( string * ) 1010 ; 1 or more integer values 1011 [ integer + ] 1013 Figure 44 1015 A repetition step expression may follow a minimum to maximum 1016 expression or the zero or more Kleene operator or the one or more 1017 Kleene operator. 1019 o When the repetition step follows a minimum to maximum expression 1020 or the zero or more Kleene operator ('*'), it specifies that the 1021 total number of repetitions present in the JSON instance being 1022 validated minus the minimum repetition value must be a multiple of 1023 the repetition step (e.g. the total repetitions minus the minimum 1024 repetition value must be divisible by the step value with a 1025 remainder of zero). 1027 o When the repetition step follows a one or more Kleene operator 1028 ('+'), the minimum repetition value is set equal to the repetition 1029 step value and the total number of repetitions minus the step 1030 value must be a multiple of the repetition step value. 1032 The following is an example for repetition steps in repetition 1033 expressions. 1035 ; there must be at least 2 name servers 1036 ; there may be no more than 12 name servers 1037 ; there must be an even number of name servers 1038 ; e.g. 2,4,6,8,10,12 1039 [ $name_servers *2..12%2 ] 1040 $name_servers =: fqdn 1042 ; minimum is zero 1043 ; maximum is 100 1044 ; must be an even number 1045 { /^eth.*/ : $mac_addr *..100%2 } 1046 $mac_addr =: hex 1048 ; at least 32 octets 1049 ; must be be in groups of 16 1050 ; e.g. 32, 48, 64 etc 1051 [ $octet *32..%16 ] 1052 $octet =: int8 1054 ; if there are to be error sets, 1055 ; their number must be divisible by 4 1056 ; e.g. 0, 4, 8, 12 etc 1057 $error_set = ( string *%4 ) 1059 ; Throws of a pair of dice must be divisible by 2 1060 ; e.g. 2, 4, 6 etc 1061 $dice_throws = ( 1..6 +%2 ) 1063 Figure 45 1065 4.14. Negating Evaluation 1067 The evaluation of a rule can be changed with the @{not} annotation. 1068 With this annotation, a rule that would otherwise match does not, and 1069 a rule that would not have matched does. 1071 ; match anything that isn't the integer 2 1072 $not_two = [ @{not} 2 ] 1074 ; error if one of the status values is "fail" 1075 $status = @{not} @{unordered} [ "fail", string * ] 1077 Figure 46 1079 5. Directives 1081 Directives modify the processing of a ruleset. There are two forms 1082 of the directive, the single line directive and the multi-line 1083 directive. 1085 Single line directives appear on their own line in a ruleset, begin 1086 with a hash character ('#') and are terminated by the end of the 1087 line. They take the following form: 1089 # directive_name parameter_1 parameter_2 ... 1091 Figure 47 1093 Multi-line directives also appear on their own lines, but may span 1094 multiple lines. They begin with the character sequence "#{" and end 1095 with "}". The take the following form: 1097 #{ directive_name 1098 parameter_1 paramter_2 1099 parameter_3 1100 ... 1101 } 1103 Figure 48 1105 This specification defines the directives "jcr-version", "ruleset- 1106 id", and "import", but other directives may be defined. 1108 5.1. jcr-version 1110 This directive declares that the ruleset complies with a specific 1111 version of this standard. The version is expressed as a major 1112 integer followed by a period followed by a minor integer. 1114 # jcr-version 0.7 1116 Figure 49 1118 The major.minor number signifying compliance with this document is 1119 "0.7". Upon publication of this specification as an IETF proposed 1120 standard, it will be "1.0". 1122 # jcr-version 1.0 1124 Figure 50 1126 Ruleset authors are advised to place this directive as the first line 1127 of a ruleset. 1129 This directive may have optional extension identifiers following the 1130 version number. Each extension identifiers is preceded by the plus 1131 ('+') character and separated by white space. The format of 1132 extension identifiers is specific to the extension, but it is 1133 recommended that they are terminated by a version number. 1135 # jcr-version 1.0 +co-constraints-1.2 +jcr-doc-1.0 1137 Figure 51 1139 5.2. ruleset-id 1141 This directive identifies a ruleset to rule processors. It takes the 1142 form: 1144 # ruleset-id identifier 1146 Figure 52 1148 An identifier can be a URL (e.g. http://example.com/foo), an inverted 1149 domain name (e.g. com.example.foo) or any other form that conforms to 1150 the JCR ABNF syntax that a ruleset author deems appropriate. To a 1151 JCR processor the identifier is treated as an opaque, case-sensitive 1152 string. 1154 5.3. import 1156 The import directive specifies that another ruleset is to have its 1157 rules evaluated in addition to the ruleset where the directive 1158 appears. 1160 The following is an example: 1162 # import http://example.com/rfc9999 as rfc9999 1164 Figure 53 1166 The rule names of the ruleset to be imported may be referenced by 1167 prepending the alias followed by a period character ('.') followed by 1168 the rule name (i.e. "alias.name"). To continue the example above, if 1169 the ruleset at http://example.com/rfc9999 were to have a rule named 1170 'encoding', rules in the ruleset importing it can refer to that rule 1171 as 'rfc9999.encoding'. 1173 6. Tips and Tricks 1175 6.1. Any Member with Any Value 1177 Because member names may be specified with regular expressions, it is 1178 possible to construct a member rule that matches any member name. As 1179 an example, the following defines an object with a member with any 1180 name that has a value that is a string: 1182 { // : string } 1184 Figure 54 1186 The JSON below matches the above rule. 1188 { "foo" : "bar" } 1190 Figure 55 1192 Likewise, the JSON below also matches the same rule. 1194 { "fuzz" : "bazz" } 1196 Figure 56 1198 Constructing an object with a member of any name with any type would 1199 therefore take the form: 1201 { // : any } 1203 Figure 57 1205 The above rule matches not only the two JSON objects above, but the 1206 JSON object below. 1208 { "fuzz" : 1234 } 1210 Figure 58 1212 6.2. Lists of Values 1214 Group specifications may be used to create enumerated lists of 1215 primitive data types, because primitive specifications may contain a 1216 group specification, which may have multiple primitive 1217 specifications. Because a primitive specification must resolve to a 1218 single data type, the group specification must only contain choice 1219 combinations. 1221 Consider the following examples: 1223 ; either an IPv4 or IPv6 adress 1224 $address =: ( ipv4 | ipv6 ) 1226 ; allowable fruits 1227 $fruits =: ( "apple" | "banana" | "pear" ) 1229 Figure 59 1231 6.3. Groups in Arrays 1233 Groups may be a subordinate component of array specifications: 1235 [ ( ipv4 | ipv6 ), integer ] 1237 Figure 60 1239 Unlike primitive specifications, subordinate group specifications in 1240 array specifications may have sequence combinations and contain any 1241 type specification. 1243 ; a group in an array 1244 [ ( $first_name, $middle_name ?, $last_name ), $age ] 1246 ; a group referenced from an array 1247 [ $name, $age ] 1248 $name = ( $first_name, $middle_name ?, $last_name ) 1250 $first_name =: string 1251 $middle_name =: string 1252 $last_name =: string 1253 $age =: 0.. 1255 Figure 61 1257 6.4. Groups in Objects 1259 Groups may be a subordinate component of object specifications: 1260 Subordinate group specifications in object specifications may have 1261 sequence combinations but must only contain member specifications. 1263 ; a group in an object 1264 { ( $title, $date, $author ), $paragraph + } 1266 ; a group referenced from an object 1267 { $front_matter, $paragraph + } 1268 $front_matter = ( $title, $date, $author ) 1270 $title = "title" : string 1271 $date = "date" : date 1272 $author = "author" : [ string * ] 1273 $paragraph = /p[0-9]*/ : string 1275 Figure 62 1277 NOTE: A future specification will clarify the choice ('|') 1278 operation as inclusive or, exclusive or ("xor") or otherwise. At 1279 present readers should assume the choice ('|') operator is an 1280 inclusive or. We are in the process of defining an algorithm to 1281 "rewrite" choices of rules for use with inclusive or which is more 1282 suitable for the data model of JSON. Such a change will impact 1283 the guidance given below. 1285 When using groups to use both sequences and choices of member 1286 specifications, consideration must be given to the processing of 1287 object specifications where by unmatched member specifications are 1288 ignored (see Figure 23). 1290 A casual reading of this rule might lead a reader to believe that the 1291 JSON object in Figure 64 would not match, however it does because the 1292 extra member (either "foo" or "baz") is not matched but is ignored. 1294 { "bar":string, ( "foo":integer | "baz":string ) } 1296 Figure 63 1298 { "bar":"thing", "foo":2, "baz": "thingy" } 1300 Figure 64 1302 The rule in Figure 63 must be modified to either match all extra 1303 rules, as in Figure 65, or the logic of the rules must be rewritten 1304 to explicitly negate the presence of the unwanted members, as in 1305 Figure 66. 1307 { "bar":string, ( "foo":integer | "baz":string ), @{not} //:any + } 1309 Figure 65 1311 { "bar":string, 1312 ( ( "foo":integer , @{not} "baz":string ) | 1313 ( "baz":string , @{not} "foo":integer ) 1314 ) } 1316 Figure 66 1318 6.5. Group Rules as Macros 1320 The syntax for group specifications accommodates one ore more 1321 subordinate components and a repetition expression for each. Other 1322 than grouping multiple rules, a group specification can be used as a 1323 macro definition for a single rule. 1325 $paragraphs = ( /p[0-9]*/ : string + ) 1327 Figure 67 1329 6.6. Object Mixins 1331 Group rules can be used to create object mixins, a pattern for 1332 writing data models similar in style to object derivation in some 1333 programming languages. In the example in below, both obj1 and obj2 1334 have a members "foo" and "fob" with obj1 having the additional member 1335 "bar" and obj2 having the additional member "baz". 1337 $mixin_group = ( "foo" : integer, "fob" : uri ) 1339 $obj1 = { $mixin_group, "bar" : string } 1341 $obj2 = { $mixin_group, "baz" : string } 1343 Figure 68 1345 6.7. Subordinate Dependencies 1347 In object and array specifications, there may be situations in which 1348 it is necessary to condition the existence of a subordinate component 1349 on the existence of a sibling subordinate component. In other words, 1350 example_two should only be evaluated if example_one evaluates 1351 positively. Or put another way, a member of an object or an item of 1352 an array may be present only on the condition that another member or 1353 item is present. 1355 In the following example, the referrer_uri member can only be present 1356 if the location_uri member is present. 1358 ; $referrer_uri can only be present if 1359 ; $location_uri is present 1360 { ( $location_uri, $referrer_uri? )? } 1362 $location_uri = "locationURI" : uri 1363 $referrer_uri = "referrerURI" : uri 1365 Figure 69 1367 7. ABNF Syntax 1369 The following ABNF describes the syntax for JSON Content Rules. A 1370 text file containing these ABNF rules can be downloaded from 1371 [JCR_ABNF]. 1373 jcr = *( sp-cmt / directive / root-rule / rule ) 1375 sp-cmt = spaces / comment 1376 spaces = 1*( WSP / CR / LF ) 1377 DSPs = ; Directive spaces 1378 1*WSP / ; When in one-line directive 1379 1*sp-cmt ; When in muti-line directive 1380 comment = ";" *comment-char comment-end-char 1381 comment-char = HTAB / %x20-10FFFF 1382 ; Any char other than CR / LF 1383 comment-end-char = CR / LF 1385 directive = "#" (one-line-directive / multi-line-directive) 1386 one-line-directive = [ DSPs ] 1387 (directive-def / one-line-tbd-directive-d) 1388 *WSP eol 1389 multi-line-directive = "{" *sp-cmt 1390 ( directive-def / 1391 multi-line-tbd-directive-d ) 1392 *sp-cmt "}" 1393 directive-def = jcr-version-d / ruleset-id-d / import-d 1394 jcr-version-d = jcr-version-kw DSPs major-version 1395 "." minor-version 1396 *( DSPs "+" [ DSPs ] extension-id ) 1397 major-version = non-neg-integer 1398 minor-version = non-neg-integer 1399 extension-id = ALPHA *not-space 1400 ruleset-id-d = ruleset-id-kw DSPs ruleset-id 1401 import-d = import-kw DSPs ruleset-id 1402 [ DSPs as-kw DSPs ruleset-id-alias ] 1403 ruleset-id = ALPHA *not-space 1404 not-space = %x21-10FFFF 1405 ruleset-id-alias = name 1406 one-line-tbd-directive-d = directive-name 1407 [ WSP one-line-directive-parameters ] 1408 directive-name = name 1409 one-line-directive-parameters = *not-eol 1410 not-eol = HTAB / %x20-10FFFF 1411 eol = CR / LF 1412 multi-line-tbd-directive-d = directive-name 1413 [ 1*sp-cmt multi-line-directive-parameters ] 1414 multi-line-directive-parameters = multi-line-parameters 1415 multi-line-parameters = *(comment / q-string / regex / 1416 not-multi-line-special) 1417 not-multi-line-special = spaces / %x21 / %x23-2E / %x30-3A / 1418 %x3C-7C / %x7E-10FFFF ; not ", /, ; or } 1420 root-rule = value-rule / group-rule 1422 rule = annotations "$" rule-name *sp-cmt 1423 "=" *sp-cmt rule-def 1425 rule-name = name 1426 target-rule-name = annotations "$" 1427 [ ruleset-id-alias "." ] 1428 rule-name 1429 name = ALPHA *( ALPHA / DIGIT / "-" / "-" ) 1431 rule-def = member-rule / type-designator rule-def-type-rule / 1432 array-rule / object-rule / group-rule / 1433 target-rule-name 1434 type-designator = type-kw 1*sp-cmt / ":" *sp-cmt 1435 rule-def-type-rule = value-rule / type-choice 1436 value-rule = primitive-rule / array-rule / object-rule 1437 member-rule = annotations 1438 member-name-spec *sp-cmt ":" *sp-cmt type-rule 1439 member-name-spec = regex / q-string 1440 type-rule = value-rule / type-choice / target-rule-name 1441 type-choice = annotations "(" type-choice-items 1442 *( choice-combiner type-choice-items ) ")" 1443 explicit-type-choice = type-designator type-choice 1444 type-choice-items = *sp-cmt ( type-choice / type-rule ) *sp-cmt 1446 annotations = *( "@{" *sp-cmt annotation-set *sp-cmt "}" 1447 *sp-cmt ) 1449 annotation-set = not-annotation / unordered-annotation / 1450 root-annotation / tbd-annotation 1451 not-annotation = not-kw 1452 unordered-annotation = unordered-kw 1453 root-annotation = root-kw 1454 tbd-annotation = annotation-name [ spaces annotation-parameters ] 1455 annotation-name = name 1456 annotation-parameters = multi-line-parameters 1458 primitive-rule = annotations primitive-def 1459 primitive-def = string-type / string-range / string-value / 1460 null-type / boolean-type / true-value / 1461 false-value / double-type / float-type / 1462 float-range / float-value / 1463 integer-type / integer-range / integer-value / 1464 sized-int-type / sized-uint-type / ipv4-type / 1465 ipv6-type / ipaddr-type / fqdn-type / idn-type / 1466 uri-type / phone-type / email-type / 1467 datetime-type / date-type / time-type / 1468 hex-type / base32hex-type / base32-type / 1469 base64url-type / base64-type / any 1470 null-type = null-kw 1471 boolean-type = boolean-kw 1472 true-value = true-kw 1473 false-value = false-kw 1474 string-type = string-kw 1475 string-value = q-string 1476 string-range = regex 1477 double-type = double-kw 1478 float-type = float-kw 1479 float-range = float-min ".." [ float-max ] / ".." float-max 1480 float-min = float 1481 float-max = float 1482 float-value = float 1483 integer-type = integer-kw 1484 integer-range = integer-min ".." [ integer-max ] / 1485 ".." integer-max 1486 integer-min = integer 1487 integer-max = integer 1488 integer-value = integer 1489 sized-int-type = int-kw pos-integer 1490 sized-uint-type = uint-kw pos-integer 1491 ipv4-type = ipv4-kw 1492 ipv6-type = ipv6-kw 1493 ipaddr-type = ipaddr-kw 1494 fqdn-type = fqdn-kw 1495 idn-type = idn-kw 1496 uri-type = uri-kw [ ".." uri-scheme ] 1497 phone-type = phone-kw 1498 email-type = email-kw 1499 datetime-type = datetime-kw 1500 date-type = date-kw 1501 time-type = time-kw 1502 hex-type = hex-kw 1503 base32hex-type = base32hex-kw 1504 base32-type = base32-kw 1505 base64url-type = base64url-kw 1506 base64-type = base64-kw 1507 any = any-kw 1509 object-rule = annotations "{" *sp-cmt 1510 [ object-items *sp-cmt ] "}" 1511 object-items = object-item (*( sequence-combiner object-item ) / 1512 *( choice-combiner object-item ) ) 1513 object-item = object-item-types *sp-cmt [ repetition ] 1514 object-item-types = object-group / member-rule / target-rule-name 1515 object-group = "(" *sp-cmt [ object-items *sp-cmt ] ")" 1517 array-rule = annotations "[" *sp-cmt [ array-items *sp-cmt ] "]" 1518 array-items = array-item (*( sequence-combiner array-item ) / 1519 *( choice-combiner array-item ) ) 1520 array-item = array-item-types *sp-cmt [ repetition ] 1521 array-item-types = array-group / type-rule / explicit-type-choice 1522 array-group = "(" *sp-cmt [ array-items *sp-cmt ] ")" 1524 group-rule = annotations "(" *sp-cmt [ group-items *sp-cmt ] ")" 1525 group-items = group-item (*( sequence-combiner group-item ) / 1526 *( choice-combiner group-item ) ) 1527 group-item = group-item-types *sp-cmt [ repetition ] 1528 group-item-types = group-group / member-rule / 1529 type-rule / explicit-type-choice 1530 group-group = group-rule 1532 sequence-combiner = *sp-cmt "," *sp-cmt 1533 choice-combiner = *sp-cmt "|" *sp-cmt 1535 repetition = optional / one-or-more / 1536 repetition-range / zero-or-more 1537 optional = "?" 1538 one-or-more = "+" [ repetition-step ] 1539 zero-or-more = "*" [ repetition-step ] 1540 repetition-range = "*" *sp-cmt ( 1541 min-max-repetition / min-repetition / 1542 max-repetition / specific-repetition ) 1543 min-max-repetition = min-repeat ".." max-repeat 1544 [ repetition-step ] 1546 min-repetition = min-repeat ".." [ repetition-step ] 1547 max-repetition = ".." max-repeat [ repetition-step ] 1548 min-repeat = non-neg-integer 1549 max-repeat = non-neg-integer 1550 specific-repetition = non-neg-integer 1551 repetition-step = "%" step-size 1552 step-size = non-neg-integer 1554 integer = "0" / ["-"] pos-integer 1555 non-neg-integer = "0" / pos-integer 1556 pos-integer = digit1-9 *DIGIT 1558 float = [ minus ] int frac [ exp ] 1559 ; From RFC 7159 except 'frac' required 1560 minus = %x2D ; - 1561 plus = %x2B ; + 1562 int = zero / ( digit1-9 *DIGIT ) 1563 digit1-9 = %x31-39 ; 1-9 1564 frac = decimal-point 1*DIGIT 1565 decimal-point = %x2E ; . 1566 exp = e [ minus / plus ] 1*DIGIT 1567 e = %x65 / %x45 ; e E 1568 zero = %x30 ; 0 1570 q-string = quotation-mark *char quotation-mark 1571 ; From RFC 7159 1572 char = unescaped / 1573 escape ( 1574 %x22 / ; " quotation mark U+0022 1575 %x5C / ; \ reverse solidus U+005C 1576 %x2F / ; / solidus U+002F 1577 %x62 / ; b backspace U+0008 1578 %x66 / ; f form feed U+000C 1579 %x6E / ; n line feed U+000A 1580 %x72 / ; r carriage return U+000D 1581 %x74 / ; t tab U+0009 1582 %x75 4HEXDIG ) ; uXXXX U+XXXX 1583 escape = %x5C ; \ 1584 quotation-mark = %x22 ; " 1585 unescaped = %x20-21 / %x23-5B / %x5D-10FFFF 1587 regex = "/" *( escape "/" / not-slash ) "/" 1588 [ regex-modifiers ] 1589 not-slash = HTAB / CR / LF / %x20-2E / %x30-10FFFF 1590 ; Any char except "/" 1591 regex-modifiers = *( "i" / "s" / "x" ) 1593 uri-scheme = 1*ALPHA 1594 ;; Keywords 1595 any-kw = %x61.6E.79 ; "any" 1596 as-kw = %x61.73 ; "as" 1597 base32-kw = %x62.61.73.65.33.32 ; "base32" 1598 base32hex-kw = %x62.61.73.65.33.32.68.65.78 ; "base32hex" 1599 base64-kw = %x62.61.73.65.36.34 ; "base64" 1600 base64url-kw = %x62.61.73.65.36.34.75.72.6C ; "base64url" 1601 boolean-kw = %x62.6F.6F.6C.65.61.6E ; "boolean" 1602 date-kw = %x64.61.74.65 ; "date" 1603 datetime-kw = %x64.61.74.65.74.69.6D.65 ; "datetime" 1604 double-kw = %x64.6F.75.62.6C.65 ; "double" 1605 email-kw = %x65.6D.61.69.6C ; "email" 1606 false-kw = %x66.61.6C.73.65 ; "false" 1607 float-kw = %x66.6C.6F.61.74 ; "float" 1608 fqdn-kw = %x66.71.64.6E ; "fqdn" 1609 hex-kw = %x68.65.78 ; "hex" 1610 idn-kw = %x69.64.6E ; "idn" 1611 import-kw = %x69.6D.70.6F.72.74 ; "import" 1612 int-kw = %x69.6E.74 ; "int" 1613 integer-kw = %x69.6E.74.65.67.65.72 ; "integer" 1614 ipaddr-kw = %x69.70.61.64.64.72 ; "ipaddr" 1615 ipv4-kw = %x69.70.76.34 ; "ipv4" 1616 ipv6-kw = %x69.70.76.36 ; "ipv6" 1617 jcr-version-kw = %x6A.63.72.2D.76.65.72.73.69.6F.6E ; "jcr-version" 1618 not-kw = %x6E.6F.74 ; "not" 1619 null-kw = %x6E.75.6C.6C ; "null" 1620 phone-kw = %x70.68.6F.6E.65 ; "phone" 1621 root-kw = %x72.6F.6F.74 ; "root" 1622 ruleset-id-kw = %x72.75.6C.65.73.65.74.2D.69.64 ; "ruleset-id" 1623 string-kw = %x73.74.72.69.6E.67 ; "string" 1624 time-kw = %x74.69.6D.65 ; "time" 1625 true-kw = %x74.72.75.65 ; "true" 1626 type-kw = %x74.79.70.65 ; "type" 1627 uint-kw = %x75.69.6E.74 ; "uint" 1628 unordered-kw = %x75.6E.6F.72.64.65.72.65.64 ; "unordered" 1629 uri-kw = %x75.72.69 ; "uri" 1631 ;; Referenced RFC 5234 Core Rules 1632 ALPHA = %x41-5A / %x61-7A ; A-Z / a-z 1633 CR = %x0D ; carriage return 1634 DIGIT = %x30-39 ; 0-9 1635 HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" 1636 HTAB = %x09 ; horizontal tab 1637 LF = %x0A ; linefeed 1638 SP = %x20 ; space 1639 WSP = SP / HTAB ; white space 1641 Figure 70: ABNF for JSON Content Rules 1643 8. Acknowledgements 1645 John Cowan, Andrew Biggs, Paul Kyzivat and Paul Jones provided 1646 feedback and suggestions which led to many changes in the syntax. 1648 9. References 1650 9.1. Normative References 1652 [RFC1166] Kirkpatrick, S., Stahl, M., and M. Recker, "Internet 1653 numbers", RFC 1166, July 1990. 1655 [RFC3339] Klyne, G., Ed. and C. Newman, "Date and Time on the 1656 Internet: Timestamps", RFC 3339, July 2002. 1658 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 1659 Resource Identifier (URI): Generic Syntax", STD 66, RFC 1660 3986, January 2005. 1662 [RFC4234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax 1663 Specifications: ABNF", RFC 4234, October 2005. 1665 [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 1666 Encodings", RFC 4648, October 2006. 1668 [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, 1669 October 2008. 1671 [RFC5952] Kawamura, S. and M. Kawashima, "A Recommendation for IPv6 1672 Address Text Representation", RFC 5952, August 2010. 1674 [RFC7159] Bray, T., "The JavaScript Object Notation (JSON) Data 1675 Interchange Format", RFC 7159, March 2014. 1677 [JCR_ABNF] 1678 Newton, A. and P. Cordell, "ABNF for JSON Content Rules", 1679 . 1682 9.2. Infomative References 1684 [I-D.cordell-jcr-co-constraints] 1685 Cordell, P. and A. Newton, "Co-Constraints for JSON 1686 Content Rules", draft-cordell-jcr-co-constraints-00 (work 1687 in progress), March 2016. 1689 [JCR_SPECIFICATION_FIGURES] 1690 Newton, A. and P. Cordell, "Figures in the JCR 1691 Specification", . 1694 [ARIN_JCR_VALIDATOR] 1695 American Registry for Internet Numbers, "JSON Content 1696 Rules Validator (Work In Progress)", 1697 . 1699 [CODALOGIC_JCR_VALIDATOR] 1700 Codalogic, "cl-jcr-parser (Work In Progress)", 1701 . 1703 Appendix A. Co-Constraints 1705 This specification defines a small set of annotations and directives 1706 for JCR, yet the syntax is extensible allowing for other annotations 1707 and directives. [I-D.cordell-jcr-co-constraints] ("Co-Constraints 1708 for JCR") defines further annotations and directives which define 1709 more detailed constraints on JSON messages, including co-constraints 1710 (constraining parts of JSON message based on another part of a JSON 1711 message). 1713 Appendix B. Testing Against JSON Content Rules 1715 One aspect of JCR that differentiates it from other format schema 1716 languages are the mechanisms helpful to developers for taking a 1717 formal specification, such as that found in an RFC, and evolving it 1718 into unit tests, which are essential to producing quality protocol 1719 implementations. 1721 B.1. Locally Overriding Rules 1723 As mentioned in the introduction, one tool for testing would be the 1724 ability to locally override named rules. As an example, consider the 1725 following rule which defines an array of strings. 1727 $statuses = [ string * ] 1729 Figure 71 1731 Consider the specification where this rule is found does not define 1732 the values but references an extensible list of possible values 1733 updated independently of the specification, such as in an IANA 1734 registry. 1736 If a software developer desired to test a specific situation in which 1737 the array must at least contain the status "accepted", the rules from 1738 the specification could be used and the statuses rule could be 1739 explicitly overridden locally as: 1741 This rule will evaluate positively with the JSON in Figure 73 1743 $statuses = @{unordered} [ "accepted", string * ] 1745 Figure 72 1747 [ "submitted", "validated", "accepted" ] 1749 Figure 73 1751 Alternatively, the developer may need to ensure that the status 1752 "denied" should not be present in the array: 1754 This rule will fail to evaluate the JSON in Figure 75 thus signaling 1755 a problem. 1757 $statuses = @{unordered} @{not} [ "denied" + , string * ] 1759 Figure 74 1761 [ "submitted", "validated", "denied" ] 1763 Figure 75 1765 B.2. Rule Callbacks 1767 In many testing scenarios, the evaluation of rules may become more 1768 complex than that which can be expressed in JCR, sometimes involving 1769 variables and interdependencies which can only be expressed in a 1770 programming language. 1772 A JCR processor may provide a mechanism for the execution of local 1773 functions or methods based on the name of a rule being evaluated. 1774 Such a mechanism could pass to the function the data to be evaluated, 1775 and that function could return to the processor the result of 1776 evaluating the data in the function. 1778 Appendix C. JCR Implementations 1780 The following implementations, [ARIN_JCR_VALIDATOR] and 1781 [CODALOGIC_JCR_VALIDATOR] have influenced the development of this 1782 document. 1784 Appendix D. Syntax Changes from -06 and -07 1786 The differences between this document and -07 are not significant, as 1787 this version of this draft is provided for the purposes of keeping 1788 the document active within the IETF archives. 1790 The syntax described in this document is changed significantly, and 1791 in a non-backwards compatible manner, from the syntax described in 1792 the -06 version of this specification. The vast majority of these 1793 changes have occurred to meet the goals of the syntax being a 1794 superset of JSON and easy to comprehend by a casual reader unfamiliar 1795 with JCR but familiar with JSON. 1797 The latter of those two goals is subjective, and therefore a series 1798 of focus group sessions were convened where participants, all 1799 professional software developers with familiarity with JSON but not 1800 JCR, were asked to read and interpret various rulesets and allowed to 1801 offer suggested improvements. Outcomes of these sessions resulted in 1802 many changes, such as the use of '$' characters to note rule names 1803 and the change of the repetition syntax. 1805 Other changes came from feedback given directly to the authors via 1806 email and on the IETF JSON Working Group mailing list. 1808 Most figures from this document can be found in file form at 1809 [JCR_SPECIFICATION_FIGURES]. 1811 Authors' Addresses 1813 Andrew Lee Newton 1814 American Registry for Internet Numbers 1815 PO Box 232290 1816 Centreville, VA 20120 1817 US 1819 Email: andy@arin.net 1820 URI: http://www.arin.net 1822 Pete Cordell 1823 Codalogic 1824 PO Box 30 1825 Ipswich IP5 2WY 1826 UK 1828 Email: pete.cordell@codalogic.com 1829 URI: http://www.codalogic.com