One document matched: draft-newton-json-content-rules-07.xml
<?xml version='1.0' encoding='ascii'?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
<?rfc toc="yes"?>
<rfc category="std" docName="draft-newton-json-content-rules-07" ipr="trust200902" obsoletes="" updates="" submissionType="IETF" xml:lang="en">
<front>
<title abbrev="JSON Content Rules">A Language for Rules Describing JSON Content</title>
<author fullname="Andrew Lee Newton" initials="A.L." surname="Newton">
<organization abbrev="ARIN">American Registry for Internet Numbers</organization>
<address>
<postal>
<street>3635 Concorde Parkway</street>
<city>Chantilly</city>
<region>VA</region>
<country>US</country>
<code>20151</code>
</postal>
<email>andy@arin.net</email>
<uri>http://www.arin.net</uri>
</address>
</author>
<author fullname="Pete Cordell" initials="P." surname="Cordell">
<organization>Codalogic</organization>
<address>
<postal>
<street>PO Box 30</street>
<city>Ipswich</city>
<country>UK</country>
<code>IP5 2WY</code>
</postal>
<email>pete.cordell@codalogic.com</email>
<uri>http://www.codalogic.com</uri>
</address>
</author>
<date/>
<abstract>
<t>This document describes a language for specifying and testing the expected content of JSON structures found in JSON-using protocols, software, and processes. </t>
</abstract>
</front>
<middle>
<section title="Introduction" toc="default">
<t>This document describes JSON Content Rules (JCR), a language for specifying and testing the interchange of data in <xref target="RFC7159" pageno="false" format="default">JSON</xref> format used by computer protocols and processes. The syntax of JCR is not JSON but is "JSON-like", possessing the conciseness and utility that has made JSON popular. </t>
<section title="A First Example: Specifying Content" toc="default">
<t>The following JSON data describes a JSON object with two members, "line-count" and "word-count", each containing an integer. </t>
<figure anchor="first_example.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "line-count" : 3426, "word-count" : 27886 }
</artwork>
</figure>
<t>This is also JCR that describes a JSON object with a member named "line-count" that is an integer that is exactly 3426 and a member named "word-count" that is an integer that is exactly 27886. </t>
<t>For a protocol specification, it is probably more useful to specify that each member is any integer and not specific, exact integers: </t>
<figure anchor="first_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "line-count" : integer, "word-count" : integer }
</artwork>
</figure>
<t>Since line counts and word counts should be either zero or a positive integer, the specification may be further narrowed: </t>
<figure anchor="first_example2.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "line-count" : 0.. , "word-count" : 0.. }
</artwork>
</figure>
</section>
<section title="A Second Example: Testing Content" toc="default">
<t>Building on the first example, this second example describes the same object but with the addition of another member, "file-name". </t>
<figure anchor="second_example.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{
"file-name" : "rfc7159.txt",
"line-count" : 3426,
"word-count" : 27886
}
</artwork>
</figure>
<t>The following JCR describes objects like it. </t>
<figure anchor="second_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{
"file-name" : string,
"line-count" : 0..,
"word-count" : 0..
}
</artwork>
</figure>
<t>For the purposes of writing a protocol specification, JCR may be broken down into named rules to reduce complexity and to enable re-use. The following example takes the JCR from above and rewrites the members as named rules. </t>
<figure anchor="second_example2.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{
$fn,
$lc,
$wc
}
$fn = "file-name" : string
$lc = "line-count" : 0..
$wc = "word-count" : 0..
</artwork>
</figure>
<t>With each member specified as a named rule, software testers can override them locally for specific test cases. In the following example, the named rules are locally overridden for the test case where the file name is "rfc4627.txt". </t>
<figure anchor="second_example_override.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$fn = "file-name" : "rfc4627.txt"
$lc = "line-count" : 2102
$wc = "word-count" : 16714
</artwork>
</figure>
<t>In this example, the protocol specification describes the JSON object in general and an implementation overrides the rules for testing specific cases. </t>
</section>
</section>
<section title="Overview of the Language" toc="default">
<t>JCR is composed of rules (as the name suggests). A collection of rules that is processed together is a ruleset. Rulesets may also contain comments, blank lines, and directives that apply to the processing of a ruleset. </t>
<t>Rules are composed of two parts, an optional rule name and a rule specification. A rule specification can be either a type specification or a member specification. A member specification consists of a member name specification and a type specification. </t>
<t>A type specification is used to specify constraints on a superset of a JSON value (e.g. number / string / object / array etc.). In addition to defining primitive types (such as string or integer), array types, and object types, type specifications may define the JCR specific concept of group types. </t>
<t>Type specifications corresponding to arrays, objects and groups may be composed of other rule specifications. </t>
<t>A member specification is used to specify constraints on a JSON member (i.e. members of a JSON object). </t>
<t>Rules with rule name assignments may be referenced in place of type specifications and member specifications. </t>
<t>Rules may be defined across line boundaries and there is no line continuation syntax. </t>
<t>Any rule consisting only of a type specification is considered a root rule. Unless otherwise specified, all the root rules of a ruleset are evaluated against a JSON instance or document. </t>
<t>Putting it all together, <xref target="rfc4627-example-1-compact-rules" pageno="false" format="default"/> describes the JSON in <xref target="rfc4627-example-1" pageno="false" format="default"/>. </t>
<figure anchor="rfc4627-example-1" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>Example JSON shamelessly lifted from RFC 4627</preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": 100
},
"IDs": [116, 943, 234, 38793]
}
}
</artwork>
</figure>
<figure anchor="rfc4627-example-1-compact-rules" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>Rules describing <xref target="rfc4627-example-1" pageno="false" format="default"/></preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; the root of the JSON instance is an object
; this root rule describes that object
{
; the object specification contains
; one member specification
"Image" : {
; $width and $height are defined below
$width,
$height,
; "Title" member specification
"Title" :string,
; "Thumbnail" member specification, which
; defines an object
"Thumbnail": {
; $width and $height are re-used again
$width, $height,
"Url" :uri
},
; "IDs" member that is an array of
; one ore more integers
"IDs" : [ integer * ]
}
}
; The definitions of the rules $width and $height
$width = "Width" : 0..1280
$height = "Height" : 0..1024
</artwork>
</figure>
</section>
<section title="Lines and Comments" toc="default">
<t>There is no statement terminator and therefore no need for a line continuation syntax. Rules may be defined across line boundaries. Blank lines are allowed. </t>
<t>Comments are the same as comments in <xref target="RFC4234" pageno="false" format="default">ABNF</xref>. They start with a semi-colon (';') and continue to the end of the line. </t>
</section>
<section title="Rules" toc="default">
<t>Rules have two main components, an optional rule name assignment and a type or member specification. </t>
<t>Type specifications define arrays, objects, etc... of JSON and may reference other rules using rule names. Most type specifications can be defined with repetitions for specifying the frequency of the type being defined. In addition to the type specifications describing JSON types, there is an additional group specification for grouping types. </t>
<t>Member specifications define members of JSON objects, and are composed of a member name specification and either a type specification or a rule name referencing a type specification. </t>
<t>Rules may also contain annotations which may affect the evaluation of all or part of a rule. Rules without a rule name assignment are considered root rules, though rules with a rule name assignment can be considered a root rule with the appropriate annotation. </t>
<t>Type specifications, depending on their type, can contain zero or more other specifications or rule names. For example, an object specification might contain multiple member specifications or rule names that resolve to member specifications or a mixture of member specifications and rule names. For the purposes of this document, specifications and rule names composing other specifications are called subordinate components. </t>
<section title="Rule Names and Assignments" toc="default">
<t>Rule names are signified with the dollar character ('$'), which is not part of the rule name itself. Rule names have two components, an optional ruleset identifier alias and a local rule name. </t>
<t>Local rule names must start with an alphabetic character (a-z,A-Z) and must contain only alphabetic characters, numeric characters, the hyphen character ('-') and the underscore character ('_'). Local rule names are case sensitive, and must be unique within a ruleset (that is, no two rule name assignments may use the same local rule name). </t>
<t>Ruleset identifier aliases enable referencing rules from another ruleset. They are not allowed in rule name assignments, and only found in rule names referencing other rules. Ruleset identifiers must start with an alphabetic character and contain no whitespace. Ruleset identifiers are case sensitive. Simple use cases of JCR will most likely not use ruleset identifiers. </t>
<figure anchor="rule_name_ruleset_id.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>In Figure 10 below, "http://ietf.org/rfcYYYY.JCR" and "http://ietf.org/rfcXXXX.JCR" are ruleset identifiers and "rfcXXXX" is a ruleset identifier alias. </preamble>
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height=""># ruleset-id http://ietf.org/rfcYYYY.JCR
# import http://ietf.org/rfcXXXX.JCR as rfcXXXX
$my_encodings = ( "mythic" | "magic" )
$all_encodings = ( $rfcXXXX.encodings | $my_encodings )
</artwork>
</figure>
<t>There are two forms of rule name assignments: assignments of primitive types and assignments of all other types. Rule name assignments to primitive type specifications separate the rule name from the type specification with the character sequence '=:', whereas rule name assignments for all other type specifications only require the separation using the '=' character. </t>
<figure anchor="assignment_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">;rule name assignments for primitive types
$foo =: "foo"
$some_string =: string
;rule name assignments for arrays
$bar = [ integer, integer, integer ]
;rule name assignement for objects
$bob = { "bar" : $bar, "foo" : $foo }
</artwork>
</figure>
<t>This is the one little "gotcha" in JCR. This syntax is necessary so that JCR parsers may readily distinguish between rule name assignments involving string and regular expressions primitive types and member names of member specifications. </t>
</section>
<section title="Annotations" toc="default">
<t>Annotations may appear before a rule name assignment, before a type or member specification, or before a rule name contained within a type specification. In each place, there may be zero or more annotations. Each annotation begins with the character sequence "@{" and ends with "}". The following is an example of a type specification with the not annotation (explained in <xref target="not_annotation" pageno="false" format="default"/>): </t>
<figure anchor="annotation_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">@{not} [ "fruits", "vegatables" ]
</artwork>
</figure>
<t>This specification defines the annotations "root", "not", and "unordered", but other annotations may be defined for other purposes. </t>
</section>
<section title="Starting Points and Root Rules" anchor="starting-points" toc="default">
<t>Evaluation of a JSON instance or document against a ruleset begins with the evaluation of a root rule or set of root rules. If no root rule (or rules) is specified locally at runtime, the set of root rules specified in the ruleset are evaluated. The order of evaluation is undefined. </t>
<t>The set of root rules specified in a ruleset is composed of all rules without a rule name assignment and all rules annotated with the "@{root}" annotation. </t>
<t>The "@{root}" annotation may either appear before a rule name assignment or before a type definition. It is ignored if present before referenced rule name inside of a type specification. </t>
</section>
<section title="Type Specifications" toc="default">
<t>The syntax of each type of type specifications varies depending on the type: </t>
<figure anchor="primitive_overview.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; primitive types can be string
; or number literals
; or number ranges
"foo"
2
1..10
; primitive types can also be more generalized types
string
integer
; primitive type rules may be named
$my_int =: 12
; member specifications consist of a member name
; followed by a colon and then followed by another
; type specification or a rule name
; (example shown with a rule name assignment)
$mem1 = "bar" : "baz"
$mem2 = "fizz" : $my_int
; member names may either be quoted strings
; or regular expressions
; (example shown with a rule name assignment)
$mem3 = /^dev[0-9]$/ : 0..4096
; object specifications start and end with "curly braces"
; object specifications contain zero
; or more member specifications
; or rule names which reference a member specification
{ $mem1, "foo" : "fuzz", "fizz" : $my_int }
; array specifications start and end with square brackets
; array specifications contain zero
; or more non-member type specifications
[ 1, 2, 3, $my_int ]
; finally, group specifications start and end with parenthesis
; groups contain other type specifications
( [ integer, integer], $rule1 )
$rule1 = [ string, string ]
</artwork>
</figure>
</section>
<section title="Primitive Specifications" toc="default">
<t>Primitive type specifications define content for JSON numbers, booleans, strings, and null. </t>
<section title="Numbers, Booleans and Null" toc="default">
<t>The rules for booleans and null are the simplest and take the following forms: </t>
<figure anchor="primitive_boolean_and_null.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">true
false
boolean
null
</artwork>
</figure>
<t>Rules for numbers can specify the number be either an integer or floating point number: </t>
<figure anchor="primitive_integer_and_float.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">integer
float
double
</artwork>
</figure>
<t>The keyword 'float' represents a single precision IEEE-754 floating point number represented in decimal. The keyword 'double' represents a double precision IEEE-754 floating point number represented in decimal format. </t>
<t>Numbers may also be specified as an absolute value or a range of possible values, where a range may be specified using a minimum, maximum, or both: </t>
<figure anchor="n_to_m" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">
n
n..m
..m
n..
n.f
n.f..m.f
..m.f
n.f..
</artwork>
</figure>
<t>When specifying a minimum and a maximum, both must either be an integer or a floating point number. Thus to specify a floating point number between zero and ten a definition of the following form is used: </t>
<figure anchor="primitive_float_range.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">0.0..10.0
</artwork>
</figure>
<t>Integers may also be specified as ranges using bit lengths preceded by the 'int' or 'uint' words (i.e. 'int8', 'uint16'). The 'int' prefix specifies the integer as being signed whereas the 'uint' prefix specifies the integer as being unsigned. </t>
<figure anchor="primitive_bit_integers.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; 0..255
uint8
; -32768..32767
int16
; 0..65535
uint16
; –9223372036854775808..9223372036854775807
int64
; 0..18446744073709551615
uint64
</artwork>
</figure>
</section>
<section title="Strings" toc="default">
<t>JCR provides a large number of data types to define the contents of JSON strings. Generically, a string may be specified using the word 'string'. String literals may be specified using a double quote character followed by the literal content followed by another double quote. And regular expressions may be specified by enclosing a regular expression within the forward slash ('/') character. </t>
<figure anchor="primitive_strings.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">; any string
string
; a string literal
"she sells sea shells"
; a regular expression
/^she sells .*/
</artwork>
</figure>
<t>Regular expressions are not implicitly anchored and therefore must be explicitly anchored if necessary. </t>
<t>A string can be specified as a <xref target="RFC3986" pageno="false" format="default">URI</xref> using the word 'uri', but also may be more narrowly scoped to a URI of a specific scheme. Specific URI schemes are specified with the word 'uri' followed by two period characters ('..') followed by the URI scheme. </t>
<figure anchor="primitive_uris.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">; any URI
uri
;a URI narrowed for an HTTPS uri
uri..https
</artwork>
</figure>
<t>IP addresses may be specified with either the word 'ipv4' for <xref target="RFC1166" pageno="false" format="default">IPv4 addresses</xref> or the word 'ipv6' for <xref target="RFC5952" pageno="false" format="default">IPv6 addresses</xref>. Fully qualified A-label and U-label domain names may be specified with the words 'fqdn' and 'idn'. </t>
<t>Dates and time can be specified as formats found in <xref target="RFC3339" pageno="false" format="default">RFC 3339</xref>. The word 'date' corresponds to the full-date ABNF rule, the word 'time' corresponds to the full-time ABNF rule, and the word 'datetime' corresponds to the 'date-time' ABNF rule. </t>
<t>Email addresses formatted according to <xref target="RFC5322" pageno="false" format="default">RFC 5322</xref> may be specified using the 'email' word, and E.123 phone numbers may be specified using the word 'phone'. </t>
<figure anchor="primitive_misc.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">;IP addresses
ipv4
ipv6
ipaddr
;domain names
fqdn
idn
; RFC 3339 full-date
date
; RFC 3339 full-time
time
; RFC 3339 date-time
datetime
; RFC 5322 email address
email
; phone number
phone
</artwork>
</figure>
<t>Binary data can be specified in string form using the encodings specified in <xref target="RFC4648" pageno="false" format="default">RFC 4648</xref>. The word 'hex' corresponds to base16, while 'base32', 'base32hex', 'base64', and 'base64url' correspond with their RFC 4648 counterparts accordingly. </t>
<figure anchor="primitive_binary.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">; RFC 4648 base16
hex
; RFC 4648 base32
base32
; RFC 4648 base32hex
base32hex
; RFC 4648 base64
base64
; RFC 4648 base64url
base64url
</artwork>
</figure>
</section>
</section>
<section title="Any Type" toc="default">
<t>It is possible to specify that a value can be of any type allowable by JSON using the word 'any'. The 'any' type specifies any primitive type, array, or object. </t>
</section>
<section title="Member Specifications" toc="default">
<t>Member specifications define members of JSON objects. Unlike other type specifications, member specifications cannot be root rules and must be part of an object specification or preceded by a rule name assignment. </t>
<t>Member specifications consist of a member name specification followed by a colon character (':') followed by either a subordinate component, which is either a rule name or a primitive, object, array, or group specification. Member name specifications can be given either as a quoted string using double quotes or as a regular expression using forward slash ('/') characters. Regular expressions are not implicitly anchored and therefore must have explicit anchors if needed. </t>
<figure anchor="member_specifications.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">;member name will exactly match "locationURI"
$location_uri = "locationURI" : uri
;member name will match "eth0", "eth1", ... "eth9"
$iface_mappings = /^eth[0-9]$/ : ipv4
</artwork>
</figure>
</section>
<section title="Object Specifications" toc="default">
<t>Object specifications define JSON objects and are composed of zero or more subordinate components, each of which can be either a rule name, member specification, or group specification. The subordinate components are enclosed at the start with a left curly brace character ('{') and at the end with a right curly brace character ('}'). </t>
<t>Evaluation of the subordinate components of object specifications is as follows: <list style="symbols"><t>No order is implied for the members of the object being evaluated. </t><t>Subordinate components of the object specification are evaluated in the order they appear. </t><t>Each member of the object being evaluated can only match one subordinate component. </t><t>Any members not matched against a subordinate component are ignored. </t></list> </t>
<t>The following examples illustrate matching of JSON objects to JCR object specifications. </t>
<figure anchor="object_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>As order is not implied for the members of objects under evaluation, the following rule will match the JSON in <xref target="object_example1.json" pageno="false" format="default"/> and <xref target="object_example2.json" pageno="false" format="default"/>. </preamble>
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">{ "locationUri" : uri, "statusCode" : integer }
</artwork>
</figure>
<figure anchor="object_example1.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">{ "locationUri" : "http://example.com", "statusCode" : 200 }
</artwork>
</figure>
<figure anchor="object_example2.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">{ "statusCode" : 200, "locationUri" : "http://example.com" }
</artwork>
</figure>
<figure anchor="object_order_eval.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>Because subordinate components of an object specification are evaluated in the order in which they are specified (i.e. left to right, top to bottom) and object members can only match one subordinate component of an object specification, the rule o1 below will not match against the JSON in <xref target="object_order_eval.json" pageno="false" format="default"/> but the rule o2 below will match it. </preamble>
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">; zero or more members that match "p0", "p1", etc
; and a member that matches "p1"
$o1 = { /^p\d+$/ : integer *, "p1" : integer }
; a member that matches "p1" and
; zero or more members that match "p0", "p1", etc
$o2 = { "p1" : integer, /^p\d+$/ : integer * }
</artwork>
<postamble>The first subordinate of rule o1 specifies that an object can have zero or more members (that is the meaning of "*", see <xref target="repetition" pageno="false" format="default"/>) where the member name is the letter 'p' followed by a number (e.g. "p0", "p1", "p2"), and the second rule specifies a member with the exact member name of "p1". Rule o2 has the exact same member specifications but in the opposite order. <xref target="object_order_eval.json" pageno="false" format="default"/> does not match rule o1 because all of the members match the first subordinate rule leaving none to match the second subordinate rule. However, rule o2 does match because the first subordinate rule matches only one member of the JSON object allowing the second subordinate rule to match the other member of the JSON object. </postamble>
</figure>
<figure anchor="object_order_eval.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">{ "p0" : 1, "p1" : 2 }
</artwork>
</figure>
<t>As stated above, members of objects which do not match a rule are ignored. The reason for this validation model is due to the nature of the typical access model to JSON objects in many programming languages, where members of the object are obtained by referencing the member name. Therefore extra members may exist without harm. </t>
<t>However, some specifications may need to restrict the members of a JSON object to a known set. To construct a rule specifying that no extra members are expected, the @{not} annotation (see <xref target="not_annotation" pageno="false" format="default"/>) may be used with a "match-all" regular expression as the last subordinate component of the object specification. </t>
<figure anchor="restrict_objects.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>The following rule will match the JSON object in <xref target="restrict_objects1.json" pageno="false" format="default"/> but will not match the JSON object in <xref target="restrict_objects2.json" pageno="false" format="default"/>. </preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "foo" : 1, "bar" : 2, @{not} // : any + }
</artwork>
</figure>
<figure anchor="restrict_objects1.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "foo" : 1, "bar" : 2 }
</artwork>
</figure>
<figure anchor="restrict_objects2.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "foo" : 1, "bar" : 2, "baz" : 3 }
</artwork>
</figure>
<t>This works because subordinate components are evaluated in the order they appear in the object rule, and the last component accepts any member with any type but fails to validate if one or more of those components are found due to the @{not} annotation. </t>
</section>
<section title="Array Specifications" toc="default">
<t>Array specifications define JSON arrays and are composed of zero or more subordinate components, each of which can either be a rule name or a primitive, array, object or group specification. The subordinate components are enclosed at the start with a left square brace character ('[') and at the end with a right square brace character (']'). </t>
<t>Evaluation of the subordinate components of array specifications is as follows: <list style="symbols"><t>The order of array items is implied unless the @{unordered} annotation is present. </t><t>Subordinate components of the array specification are evaluated in the order they appear. </t><t>Each item of the array being evaluated can only match one subordinate component of the array specification. </t><t>If any items of the array are not matched, then the array does not match the array specification. </t></list> These rules are further explained in the examples below. </t>
<figure anchor="array_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">[ 0..1024, 0..980 ]
</artwork>
</figure>
<t>Unlike object specifications, order is implied in array specifications by default. That is, the first subordinate component will match the first element of the array, the second subordinate component will match the second element of the array, and so on. </t>
<t>Take for example the following ruleset: </t>
<figure anchor="array_order_eval.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">; the first element of the array is to be a string
; the second element of the array is to be an integer
$a1 = [ string, integer ]
; the first element of the array is to be an integer
; the second element of the array is to be a string
$a2 = [ integer, string ]
</artwork>
</figure>
<t>It defines two rules, a1 and a2. The array in the following JSON will not match a1, but will match a2. </t>
<figure anchor="array_order_eval.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">[ 24, "Bob Smurd" ]
</artwork>
</figure>
<t>If an array has more elements than can be matched from the array specification, the array does not match the array specification. Or stated differently, an array with unmatched elements does not validate. Using the example array rule a2 from above, the following array does not match because the last element of the array does not match any subordinate component: </t>
<figure anchor="array_order_eval2.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">[ 24, "Bob Smurd", "http://example.com/bob_smurd" ]
</artwork>
</figure>
<t>To allow an array to contain any value after guaranteeing that it contains the necessary items, the last subordinate component of the array specification should accept any item: </t>
<figure anchor="unrestricted_arrays.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; the first element of the array is to be an integer
; the second element of the array is to be a string
; anything else can follow
$a3 = [ integer, string, any * ]
</artwork>
<postamble>The JSON array in <xref target="array_order_eval2.json" pageno="false" format="default"/> will validate against the a3 rule in this example. </postamble>
</figure>
<section title="Unordered Array Specifications" anchor="unordered_array_specifications" toc="default">
<t>Array specifications can be made to behave in a similar fashion to object specifications with regard to the order of matching with the @{unordered} annotation. </t>
<t>In the ruleset below, a1 and a2 have the same subordinate components given in the same order. a2 is annotated with the @{unordered} annotation. </t>
<figure anchor="array_unordered_eval.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">$a1 = [ string, integer ]
$a2 = @{unordered} [ string, integer ]
</artwork>
</figure>
<t>The JSON array below does not match a1 but does match a2. </t>
<figure anchor="array_order_eval.json_2" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">[ 24, "Bob Smurd" ]
</artwork>
</figure>
<t>Like ordered array specifications, the subordinate components in an unordered array specification are evaluated in the order they are specified. The difference is that they need not match an element of the array in the same position as given in the array specification. </t>
<t>Finally, like ordered array specifications, unordered array specifications also require that all elements of the array be matched by a subordinate component. If the array has more elements than can be matched, the array does not match the array specification. </t>
</section>
</section>
<section title="Group Specifications" anchor="group_specifications" toc="default">
<t>Unlike the other type specifications, group specifications have no direct tie with JSON syntax. Group specifications simply group together their subordinate components. Group specifications enclose one or more subordinate components with the parenthesis characters. </t>
<t>Group specifications and any nesting of group specifications, must conform to the allowable set of type specifications of the type specifications in which they are contained. For example, a group specification inside of an array specification may not contain a member specification since member specifications are not allowed as direct subordinates of array specifications (arrays contain values, not object members in JSON). Likewise, a group specification referenced inside an object specification must only contain member specifications (JSON objects may only contain object members). </t>
<t>The following is an example of a group specification: </t>
<figure anchor="group_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$the_bradys = [ $parents, $children ]
$children = ( "Greg", "Marsha", "Bobby", "Jan" )
$parents = ( "Mike", "Carol" )
</artwork>
</figure>
<t>Like the subordinate components of array and object specifications, the subordinate components of a group specification are evaluated in the order they appear. </t>
</section>
<section title="Ordered and Unordered Groups in Arrays" toc="default">
<t><xref target="unordered_array_specifications" pageno="false" format="default"/> specifies that arrays can be evaluated by the order of the items in the array or can be evaluated without order. <xref target="group_specifications" pageno="false" format="default"/> specifies that arrays may have group rules as subordinate components. </t>
<t>The evaluation of a group specification inside an array specification inherits the ordering property of the array specification. If the array specification is unordered, then the items of the group specification are also considered to be unordered. And if the array specification is ordered, then the items of the group specification are also considered to be ordered. </t>
</section>
<section title="Sequence and Choice Combinations in Array, Object, and Group Specifications" toc="default">
<t>Combinations of subordinate components in array, object, and group specifications can be specified as either a sequence ("and") or a choice ("or"). A sequence is a subordinate component followed by the comma character (',') followed by another subordinate component. A choice is a subordinate component followed by a pipe character ('|') followed by another subordinate component. </t>
<figure anchor="and_or_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">; sequence ("and")
[ "this" , "that" ]
; choice ("or")
[ "this" | "that" ]
</artwork>
</figure>
<t>Sequence and choice combinations cannot be mixed, and group specifications must be used to explicitly declare precedence between a sequence and a choice. Therefore, the following is illegal: </t>
<figure anchor="mixed_and_or_bad.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">[ "this", "that" | "the_other" ]
</artwork>
</figure>
<t>The example above should be expressed as: </t>
<figure anchor="mixed_and_or_good.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">[ "this", ( "that" | "the_other" ) ]
</artwork>
</figure>
<t><list style="none"><t>NOTE: A future specification will clarify the choice ('|') operation as inclusive or, exclusive or ("xor") or otherwise. At present readers should assume the choice ('|') operator is an inclusive or. However, for objects and unordered arrays that is not ideal, nor is xor. We are in the process of defining an algorithm to "rewrite" choices of rules for use with inclusive or which is more suitable for the data model of JSON. </t></list> </t>
</section>
<section title="Repetition in Array, Object, and Group Specifications" anchor="repetition" toc="default">
<t>Evaluation of subordinate components in array, object, and group specifications may be succeeded by a repetition expression denoting how many times the subordinate component should be evaluated. Repetition expressions are specified using a Kleene symbol ('?', '+', or '*') or with the '*' symbol succeeded by specific minimum and/or maximum values, each being non-negative integers. Repetition expressions may also be appended with a step expression, which is the '%' symbol followed by a positive integer. </t>
<t>When no repetition expression is present, both the minimum and maximum are 1. </t>
<t>A minimum and maximum can be expressed by giving the minimum followed by two period characters ('..') followed by the maximum, with either the minimum or maximum being optional. When the minimum is not explicitly specified, it is assumed to be zero. When the maximum is not explicitly specified, it is assumed to be positive infinity. </t>
<figure anchor="repetition_min_max.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; exactly 2 octets
$word = [ $octet *2 ]
$octet =: int8
; 1 to 13 name servers
[ $name_servers *1..13 ]
$name_servers =: fqdn
; 0 to 99 ethernet addresses
{ /^eth.*/ : $mac_addr *..99 }
$mac_addr =: hex
; four or more bytes
[ $octet *4.. ]
</artwork>
</figure>
<t>The allowable Kleene operators are the question mark character ('?') which specifies zero or one (i.e. optional), the plus character ('+') which specifies one or more, and the asterisk character ('*') which specifies zero or more. </t>
<figure anchor="repetition_kleene.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; age is optional
{ "name" : string, "age" : integer ? }
; zero or more errors
$error_set = ( string * )
; 1 or more integer values
[ integer + ]
</artwork>
</figure>
<t>A repetition step expression may follow a minimum to maximum expression or the zero or more Kleene operator or the one or more Kleene operator. <list style="symbols"><t>When the repetition step follows a minimum to maximum expression or the zero or more Kleene operator ('*'), it specifies that the total number of repetitions present in the JSON instance being validated minus the minimum repetition value must be a multiple of the repetition step (e.g. the total repetitions minus the minimum repetition value must be divisible by the step value with a remainder of zero). </t><t>When the repetition step follows a one or more Kleene operator ('+'), the minimum repetition value is set equal to the repetition step value and the total number of repetitions minus the step value must be a multiple of the repetition step value. </t></list> </t>
<figure anchor="repetition_step.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>The following is an example for repetition steps in repetition expressions.</preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; there must be at least 2 name servers
; there may be no more than 12 name servers
; there must be an even number of name servers
; e.g. 2,4,6,8,10,12
[ $name_servers *2..12%2 ]
$name_servers =: fqdn
; minimum is zero
; maximum is 100
; must be an even number
{ /^eth.*/ : $mac_addr *..100%2 }
$mac_addr =: hex
; at least 32 octets
; must be be in groups of 16
; e.g. 32, 48, 64 etc
[ $octet *32..%16 ]
$octet =: int8
; if there are to be error sets,
; their number must be divisible by 4
; e.g. 0, 4, 8, 12 etc
$error_set = ( string *%4 )
; Throws of a pair of dice must be divisible by 2
; e.g. 2, 4, 6 etc
$dice_throws = ( 1..6 +%2 )
</artwork>
</figure>
</section>
<section title="Negating Evaluation" anchor="not_annotation" toc="default">
<t>The evaluation of a rule can be changed with the @{not} annotation. With this annotation, a rule that would otherwise match does not, and a rule that would not have matched does. <figure anchor="not_annotation.jcr" title="" suppress-title="false" align="left" alt="" width="" height=""><artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; match anything that isn't the integer 2
$not_two = [ @{not} 2 ]
; error if one of the status values is "fail"
$status = @{not} @{unordered} [ "fail", string * ]
</artwork></figure> </t>
</section>
</section>
<section title="Directives" toc="default">
<t>Directives modify the processing of a ruleset. There are two forms of the directive, the single line directive and the multi-line directive. </t>
<t>Single line directives appear on their own line in a ruleset, begin with a hash character ('#') and are terminated by the end of the line. They take the following form: </t>
<figure anchor="single_line_directive_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height=""># directive_name parameter_1 parameter_2 ...
</artwork>
</figure>
<t>Multi-line directives also appear on their own lines, but may span multiple lines. They begin with the character sequence "#{" and end with "}". The take the following form: </t>
<figure anchor="multi_line_directive_example.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">#{ directive_name
parameter_1 paramter_2
parameter_3
...
}
</artwork>
</figure>
<t>This specification defines the directives "jcr-version", "ruleset-id", and "import", but other directives may be defined. </t>
<section title="jcr-version" toc="default">
<!--We'll obviously have to revisit this section upon publication.-->
<t>This directive declares that the ruleset complies with a specific version of this standard. The version is expressed as a major integer followed by a period followed by a minor integer. </t>
<figure anchor="jcr_version_current.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height=""># jcr-version 0.7
</artwork>
</figure>
<t>The major.minor number signifying compliance with this document is "0.7". Upon publication of this specification as an IETF proposed standard, it will be "1.0". <cref>NOTE: This will be removed in the final version. </cref> </t>
<!--This will be put into a file when the jcr validator actually accepts 1.0. Right now it accepts the working version number. -->
<figure anchor="jcr_version_final.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">
# jcr-version 1.0
</artwork>
</figure>
<t>Ruleset authors are advised to place this directive as the first line of a ruleset. </t>
<t>This directive may have optional extension identifiers following the version number. Each extension identifiers is preceded by the plus ('+') character and separated by white space. The format of extension identifiers is specific to the extension, but it is recommended that they are terminated by a version number. </t>
<!--This will be put into a file when the jcr validator actually accepts 1.0. Right now it accepts the working version number. -->
<figure anchor="jcr_version_extensions.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">
# jcr-version 1.0 +co-constraints-1.2 +jcr-doc-1.0
</artwork>
</figure>
</section>
<section title="ruleset-id" toc="default">
<t>This directive identifies a ruleset to rule processors. It takes the form: </t>
<figure anchor="ruleset_id.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height=""># ruleset-id identifier
</artwork>
</figure>
<t>An identifier can be a URL (e.g. http://example.com/foo), an inverted domain name (e.g. com.example.foo) or any other form that conforms to the JCR ABNF syntax that a ruleset author deems appropriate. To a JCR processor the identifier is treated as an opaque, case-sensitive string. </t>
</section>
<section title="import" toc="default">
<t>The import directive specifies that another ruleset is to have its rules evaluated in addition to the ruleset where the directive appears. </t>
<t>The following is an example: </t>
<!--We don't have control of example.com, so this can't be put in as a test.-->
<figure anchor="import_directive.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">
# import http://example.com/rfc9999 as rfc9999
</artwork>
</figure>
<t>The rule names of the ruleset to be imported may be referenced by prepending the alias followed by a period character ('.') followed by the rule name (i.e. "alias.name"). To continue the example above, if the ruleset at http://example.com/rfc9999 were to have a rule named 'encoding', rules in the ruleset importing it can refer to that rule as 'rfc9999.encoding'. </t>
</section>
</section>
<section title="Tips and Tricks" toc="default">
<section title="Any Member with Any Value" toc="default">
<t>Because member names may be specified with regular expressions, it is possible to construct a member rule that matches any member name. As an example, the following defines an object with a member with any name that has a value that is a string: </t>
<figure anchor="any_member.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ // : string }
</artwork>
</figure>
<t>The JSON below matches the above rule. </t>
<figure anchor="any_member1.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "foo" : "bar" }
</artwork>
</figure>
<t>Likewise, the JSON below also matches the same rule. </t>
<figure anchor="any_member2.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "fuzz" : "bazz" }
</artwork>
</figure>
<t>Constructing an object with a member of any name with any type would therefore take the form: </t>
<figure anchor="any_member_any_type.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ // : any }
</artwork>
</figure>
<t>The above rule matches not only the two JSON objects above, but the JSON object below. </t>
<figure anchor="any_member_any_type2.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "fuzz" : 1234 }
</artwork>
</figure>
</section>
<section title="Lists of Values" toc="default">
<t>Group specifications may be used to create enumerated lists of primitive data types, because primitive specifications may contain a group specification, which may have multiple primitive specifications. Because a primitive specification must resolve to a single data type, the group specification must only contain choice combinations. </t>
<t>Consider the following examples: </t>
<figure anchor="lists_of_values.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; either an IPv4 or IPv6 adress
$address =: ( ipv4 | ipv6 )
; allowable fruits
$fruits =: ( "apple" | "banana" | "pear" )
</artwork>
</figure>
</section>
<section title="Groups in Arrays" toc="default">
<t>Groups may be a subordinate component of array specifications: </t>
<figure anchor="groups_in_arrays.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">[ ( ipv4 | ipv6 ), integer ]
</artwork>
</figure>
<t>Unlike primitive specifications, subordinate group specifications in array specifications may have sequence combinations and contain any type specification. </t>
<figure anchor="groups_in_arrays2.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; a group in an array
[ ( $first_name, $middle_name ?, $last_name ), $age ]
; a group referenced from an array
[ $name, $age ]
$name = ( $first_name, $middle_name ?, $last_name )
$first_name =: string
$middle_name =: string
$last_name =: string
$age =: 0..
</artwork>
</figure>
</section>
<section title="Groups in Objects" toc="default">
<t>Groups may be a subordinate component of object specifications: Subordinate group specifications in object specifications may have sequence combinations but must only contain member specifications. </t>
<figure anchor="groups_in_objects.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; a group in an object
{ ( $title, $date, $author ), $paragraph + }
; a group referenced from an object
{ $front_matter, $paragraph + }
$front_matter = ( $title, $date, $author )
$title = "title" : string
$date = "date" : date
$author = "author" : [ string * ]
$paragraph = /p[0-9]*/ : string
</artwork>
</figure>
<t><list style="none"><t>NOTE: A future specification will clarify the choice ('|') operation as inclusive or, exclusive or ("xor") or otherwise. At present readers should assume the choice ('|') operator is an inclusive or. We are in the process of defining an algorithm to "rewrite" choices of rules for use with inclusive or which is more suitable for the data model of JSON. Such a change will impact the guidance given below. </t></list> </t>
<t>When using groups to use both sequences and choices of member specifications, consideration must be given to the processing of object specifications where by unmatched member specifications are ignored (see <xref target="member_specifications.jcr" pageno="false" format="default"/>). </t>
<figure anchor="groups_in_objects_ignored1.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>A casual reading of this rule might lead a reader to believe that the JSON object in <xref target="groups_in_objects_ignored.json" pageno="false" format="default"/> would not match, however it does because the extra member (either "foo" or "baz") is not matched but is ignored. </preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "bar":string, ( "foo":integer | "baz":string ) }
</artwork>
</figure>
<figure anchor="groups_in_objects_ignored.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">{ "bar":"thing", "foo":2, "baz": "thingy" }
</artwork>
</figure>
<t>The rule in <xref target="groups_in_objects_ignored1.jcr" pageno="false" format="default"/> must be modified to either match all extra rules, as in <xref target="groups_in_objects_ignored2.jcr" pageno="false" format="default"/>, or the logic of the rules must be rewritten to explicitly negate the presence of the unwanted members, as in <xref target="groups_in_objects_ignored3.jcr" pageno="false" format="default"/>. </t>
<figure anchor="groups_in_objects_ignored2.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">{ "bar":string, ( "foo":integer | "baz":string ), @{not} //:any + }
</artwork>
</figure>
<figure anchor="groups_in_objects_ignored3.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork align="center" xml:space="preserve" name="" type="" alt="" width="" height="">{ "bar":string,
( ( "foo":integer , @{not} "baz":string ) |
( "baz":string , @{not} "foo":integer )
) }
</artwork>
</figure>
</section>
<section title="Group Rules as Macros" toc="default">
<t>The syntax for group specifications accommodates one ore more subordinate components and a repetition expression for each. Other than grouping multiple rules, a group specification can be used as a macro definition for a single rule. </t>
<figure anchor="macro.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$paragraphs = ( /p[0-9]*/ : string + )
</artwork>
</figure>
</section>
<section title="Object Mixins" toc="default">
<t>Group rules can be used to create object mixins, a pattern for writing data models similar in style to object derivation in some programming languages. In the example in below, both obj1 and obj2 have a members "foo" and "fob" with obj1 having the additional member "bar" and obj2 having the additional member "baz". </t>
<figure anchor="object_mixin.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$mixin_group = ( "foo" : integer, "fob" : uri )
$obj1 = { $mixin_group, "bar" : string }
$obj2 = { $mixin_group, "baz" : string }
</artwork>
</figure>
</section>
<section title="Subordinate Dependencies" toc="default">
<t>In object and array specifications, there may be situations in which it is necessary to condition the existence of a subordinate component on the existence of a sibling subordinate component. In other words, example_two should only be evaluated if example_one evaluates positively. Or put another way, a member of an object or an item of an array may be present only on the condition that another member or item is present. </t>
<t>In the following example, the referrer_uri member can only be present if the location_uri member is present. </t>
<figure anchor="subordinate_dependents.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">; $referrer_uri can only be present if
; $location_uri is present
{ ( $location_uri, $referrer_uri? )? }
$location_uri = "locationURI" : uri
$referrer_uri = "referrerURI" : uri
</artwork>
</figure>
</section>
</section>
<section title="ABNF Syntax" toc="default">
<figure title="ABNF for JSON Content Rules" anchor="abnf" suppress-title="false" align="left" alt="" width="" height="">
<preamble>The following ABNF describes the syntax for JSON Content Rules. A text file containing these ABNF rules can be downloaded from <xref target="JCR_ABNF" pageno="false" format="default"/>. </preamble>
<artwork xml:space="preserve" name="" type="" align="left" alt="" width="" height="">jcr = *( sp-cmt / directive / root-rule / rule )
sp-cmt = spaces / comment
spaces = 1*( WSP / CR / LF )
DSPs = ; Directive spaces
1*WSP / ; When in one-line directive
1*sp-cmt ; When in muti-line directive
comment = ";" *comment-char comment-end-char
comment-char = HTAB / %x20-10FFFF
; Any char other than CR / LF
comment-end-char = CR / LF
directive = "#" (one-line-directive / multi-line-directive)
one-line-directive = [ DSPs ]
(directive-def / one-line-tbd-directive-d)
*WSP eol
multi-line-directive = "{" *sp-cmt
( directive-def /
multi-line-tbd-directive-d )
*sp-cmt "}"
directive-def = jcr-version-d / ruleset-id-d / import-d
jcr-version-d = jcr-version-kw DSPs major-version
"." minor-version
*( DSPs "+" [ DSPs ] extension-id )
major-version = non-neg-integer
minor-version = non-neg-integer
extension-id = ALPHA *not-space
ruleset-id-d = ruleset-id-kw DSPs ruleset-id
import-d = import-kw DSPs ruleset-id
[ DSPs as-kw DSPs ruleset-id-alias ]
ruleset-id = ALPHA *not-space
not-space = %x21-10FFFF
ruleset-id-alias = name
one-line-tbd-directive-d = directive-name
[ WSP one-line-directive-parameters ]
directive-name = name
one-line-directive-parameters = *not-eol
not-eol = HTAB / %x20-10FFFF
eol = CR / LF
multi-line-tbd-directive-d = directive-name
[ 1*sp-cmt multi-line-directive-parameters ]
multi-line-directive-parameters = multi-line-parameters
multi-line-parameters = *(comment / q-string / regex /
not-multi-line-special)
not-multi-line-special = spaces / %x21 / %x23-2E / %x30-3A /
%x3C-7C / %x7E-10FFFF ; not ", /, ; or }
root-rule = value-rule / group-rule
rule = annotations "$" rule-name *sp-cmt
"=" *sp-cmt rule-def
rule-name = name
target-rule-name = annotations "$"
[ ruleset-id-alias "." ]
rule-name
name = ALPHA *( ALPHA / DIGIT / "-" / "-" )
rule-def = member-rule / type-designator rule-def-type-rule /
array-rule / object-rule / group-rule /
target-rule-name
type-designator = type-kw 1*sp-cmt / ":" *sp-cmt
rule-def-type-rule = value-rule / type-choice
value-rule = primitive-rule / array-rule / object-rule
member-rule = annotations
member-name-spec *sp-cmt ":" *sp-cmt type-rule
member-name-spec = regex / q-string
type-rule = value-rule / type-choice / target-rule-name
type-choice = annotations "(" type-choice-items
*( choice-combiner type-choice-items ) ")"
explicit-type-choice = type-designator type-choice
type-choice-items = *sp-cmt ( type-choice / type-rule ) *sp-cmt
annotations = *( "@{" *sp-cmt annotation-set *sp-cmt "}"
*sp-cmt )
annotation-set = not-annotation / unordered-annotation /
root-annotation / tbd-annotation
not-annotation = not-kw
unordered-annotation = unordered-kw
root-annotation = root-kw
tbd-annotation = annotation-name [ spaces annotation-parameters ]
annotation-name = name
annotation-parameters = multi-line-parameters
primitive-rule = annotations primitive-def
primitive-def = string-type / string-range / string-value /
null-type / boolean-type / true-value /
false-value / double-type / float-type /
float-range / float-value /
integer-type / integer-range / integer-value /
sized-int-type / sized-uint-type / ipv4-type /
ipv6-type / ipaddr-type / fqdn-type / idn-type /
uri-type / phone-type / email-type /
datetime-type / date-type / time-type /
hex-type / base32hex-type / base32-type /
base64url-type / base64-type / any
null-type = null-kw
boolean-type = boolean-kw
true-value = true-kw
false-value = false-kw
string-type = string-kw
string-value = q-string
string-range = regex
double-type = double-kw
float-type = float-kw
float-range = float-min ".." [ float-max ] / ".." float-max
float-min = float
float-max = float
float-value = float
integer-type = integer-kw
integer-range = integer-min ".." [ integer-max ] /
".." integer-max
integer-min = integer
integer-max = integer
integer-value = integer
sized-int-type = int-kw pos-integer
sized-uint-type = uint-kw pos-integer
ipv4-type = ipv4-kw
ipv6-type = ipv6-kw
ipaddr-type = ipaddr-kw
fqdn-type = fqdn-kw
idn-type = idn-kw
uri-type = uri-kw [ ".." uri-scheme ]
phone-type = phone-kw
email-type = email-kw
datetime-type = datetime-kw
date-type = date-kw
time-type = time-kw
hex-type = hex-kw
base32hex-type = base32hex-kw
base32-type = base32-kw
base64url-type = base64url-kw
base64-type = base64-kw
any = any-kw
object-rule = annotations "{" *sp-cmt
[ object-items *sp-cmt ] "}"
object-items = object-item (*( sequence-combiner object-item ) /
*( choice-combiner object-item ) )
object-item = object-item-types *sp-cmt [ repetition ]
object-item-types = object-group / member-rule / target-rule-name
object-group = "(" *sp-cmt [ object-items *sp-cmt ] ")"
array-rule = annotations "[" *sp-cmt [ array-items *sp-cmt ] "]"
array-items = array-item (*( sequence-combiner array-item ) /
*( choice-combiner array-item ) )
array-item = array-item-types *sp-cmt [ repetition ]
array-item-types = array-group / type-rule / explicit-type-choice
array-group = "(" *sp-cmt [ array-items *sp-cmt ] ")"
group-rule = annotations "(" *sp-cmt [ group-items *sp-cmt ] ")"
group-items = group-item (*( sequence-combiner group-item ) /
*( choice-combiner group-item ) )
group-item = group-item-types *sp-cmt [ repetition ]
group-item-types = group-group / member-rule /
type-rule / explicit-type-choice
group-group = group-rule
sequence-combiner = *sp-cmt "," *sp-cmt
choice-combiner = *sp-cmt "|" *sp-cmt
repetition = optional / one-or-more /
repetition-range / zero-or-more
optional = "?"
one-or-more = "+" [ repetition-step ]
zero-or-more = "*" [ repetition-step ]
repetition-range = "*" *sp-cmt (
min-max-repetition / min-repetition /
max-repetition / specific-repetition )
min-max-repetition = min-repeat ".." max-repeat
[ repetition-step ]
min-repetition = min-repeat ".." [ repetition-step ]
max-repetition = ".." max-repeat [ repetition-step ]
min-repeat = non-neg-integer
max-repeat = non-neg-integer
specific-repetition = non-neg-integer
repetition-step = "%" step-size
step-size = non-neg-integer
integer = "0" / ["-"] pos-integer
non-neg-integer = "0" / pos-integer
pos-integer = digit1-9 *DIGIT
float = [ minus ] int frac [ exp ]
; From RFC 7159 except 'frac' required
minus = %x2D ; -
plus = %x2B ; +
int = zero / ( digit1-9 *DIGIT )
digit1-9 = %x31-39 ; 1-9
frac = decimal-point 1*DIGIT
decimal-point = %x2E ; .
exp = e [ minus / plus ] 1*DIGIT
e = %x65 / %x45 ; e E
zero = %x30 ; 0
q-string = quotation-mark *char quotation-mark
; From RFC 7159
char = unescaped /
escape (
%x22 / ; " quotation mark U+0022
%x5C / ; \ reverse solidus U+005C
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX
escape = %x5C ; \
quotation-mark = %x22 ; "
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
regex = "/" *( escape "/" / not-slash ) "/"
[ regex-modifiers ]
not-slash = HTAB / CR / LF / %x20-2E / %x30-10FFFF
; Any char except "/"
regex-modifiers = *( "i" / "s" / "x" )
uri-scheme = 1*ALPHA
;; Keywords
any-kw = %x61.6E.79 ; "any"
as-kw = %x61.73 ; "as"
base32-kw = %x62.61.73.65.33.32 ; "base32"
base32hex-kw = %x62.61.73.65.33.32.68.65.78 ; "base32hex"
base64-kw = %x62.61.73.65.36.34 ; "base64"
base64url-kw = %x62.61.73.65.36.34.75.72.6C ; "base64url"
boolean-kw = %x62.6F.6F.6C.65.61.6E ; "boolean"
date-kw = %x64.61.74.65 ; "date"
datetime-kw = %x64.61.74.65.74.69.6D.65 ; "datetime"
double-kw = %x64.6F.75.62.6C.65 ; "double"
email-kw = %x65.6D.61.69.6C ; "email"
false-kw = %x66.61.6C.73.65 ; "false"
float-kw = %x66.6C.6F.61.74 ; "float"
fqdn-kw = %x66.71.64.6E ; "fqdn"
hex-kw = %x68.65.78 ; "hex"
idn-kw = %x69.64.6E ; "idn"
import-kw = %x69.6D.70.6F.72.74 ; "import"
int-kw = %x69.6E.74 ; "int"
integer-kw = %x69.6E.74.65.67.65.72 ; "integer"
ipaddr-kw = %x69.70.61.64.64.72 ; "ipaddr"
ipv4-kw = %x69.70.76.34 ; "ipv4"
ipv6-kw = %x69.70.76.36 ; "ipv6"
jcr-version-kw = %x6A.63.72.2D.76.65.72.73.69.6F.6E ; "jcr-version"
not-kw = %x6E.6F.74 ; "not"
null-kw = %x6E.75.6C.6C ; "null"
phone-kw = %x70.68.6F.6E.65 ; "phone"
root-kw = %x72.6F.6F.74 ; "root"
ruleset-id-kw = %x72.75.6C.65.73.65.74.2D.69.64 ; "ruleset-id"
string-kw = %x73.74.72.69.6E.67 ; "string"
time-kw = %x74.69.6D.65 ; "time"
true-kw = %x74.72.75.65 ; "true"
type-kw = %x74.79.70.65 ; "type"
uint-kw = %x75.69.6E.74 ; "uint"
unordered-kw = %x75.6E.6F.72.64.65.72.65.64 ; "unordered"
uri-kw = %x75.72.69 ; "uri"
;; Referenced RFC 5234 Core Rules
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
CR = %x0D ; carriage return
DIGIT = %x30-39 ; 0-9
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
HTAB = %x09 ; horizontal tab
LF = %x0A ; linefeed
SP = %x20 ; space
WSP = SP / HTAB ; white space
</artwork>
</figure>
</section>
<section title="Acknowledgements" toc="default">
<t>John Cowan, Andrew Biggs, Paul Kyzivat and Paul Jones provided feedback and suggestions which led to many changes in the syntax. </t>
</section>
</middle>
<back>
<references title="Normative References"><reference anchor="RFC1166"><front><title abbrev="Internet Numbers">Internet numbers</title><author initials="S." surname="Kirkpatrick" fullname="Sue Kirkpatrick"><organization>SRI International, Network Information Systems Center</organization><address><postal><street>333 Ravenswood Avenue</street><street>EJ217</street><city>Menlo Park</city><region>CA</region><code>94025</code><country>US</country></postal><phone>+1 415 859 5539</phone><email>SUE@NIC.DDN.MIL</email></address></author><author initials="M." surname="Stahl" fullname="Mary Stahl"><organization>SRI International, Network Information Systems Center</organization><address><postal><street>333 Ravenswood Avenue</street><street>EJ296</street><city>Menlo Park</city><region>CA</region><code>94025</code><country>US</country></postal><phone>+1 415 859 4775</phone><email>STAHL@NIC.DDN.MIL</email></address></author><author initials="M." surname="Recker" fullname="Mimi Recker"><organization>SRI International, Network Information Systems Center</organization><address><postal><street>333 Ravenswood Avenue</street><street>EJ268</street><city>Menlo Park</city><region>CA</region><code>94025</code><country>US</country></postal><phone>+1 415 859 2110</phone><email>MIMI@NIC.DDN.MIL</email></address></author><date year="1990" day="1" month="July"/></front><seriesInfo name="RFC" value="1166"/><format type="TXT" octets="566778" target="http://www.rfc-editor.org/rfc/rfc1166.txt"/></reference> <reference anchor="RFC3339"><front><title>Date and Time on the Internet: Timestamps</title><author initials="G." surname="Klyne" fullname="Graham Klyne" role="editor"><organization>Clearswift Corporation</organization><address><postal><street>1310 Waterside</street><street>Arlington Business Park</street><city>Theale</city><region>Reading</region><code>RG7 4SA</code><country>UK</country></postal><phone>+44 11 8903 8903</phone><facsimile>+44 11 8903 9000</facsimile><email>GK@ACM.ORG</email></address></author><author initials="C." surname="Newman" fullname="Chris Newman"><organization>Sun Microsystems</organization><address><postal><street>1050 Lakes Drive, Suite 250</street><city>West Covina</city><region>CA</region><code>91790</code><country>USA</country></postal><email>chris.newman@sun.com</email></address></author><date year="2002" month="July"/><abstract><t>This document defines a date and time format for use in Internet protocols that is a profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. </t></abstract></front><seriesInfo name="RFC" value="3339"/><format type="TXT" octets="35064" target="http://www.rfc-editor.org/rfc/rfc3339.txt"/><format type="HTML" octets="65570" target="http://xml.resource.org/public/rfc/html/rfc3339.html"/><format type="XML" octets="37259" target="http://xml.resource.org/public/rfc/xml/rfc3339.xml"/></reference> <reference anchor="RFC3986"><front><title abbrev="URI Generic Syntax">Uniform Resource Identifier (URI): Generic Syntax</title><author initials="T." surname="Berners-Lee" fullname="Tim Berners-Lee"><organization abbrev="W3C/MIT">World Wide Web Consortium</organization><address><postal><street>Massachusetts Institute of Technology</street><street>77 Massachusetts Avenue</street><city>Cambridge</city><region>MA</region><code>02139</code><country>USA</country></postal><phone>+1-617-253-5702</phone><facsimile>+1-617-258-5999</facsimile><email>timbl@w3.org</email><uri>http://www.w3.org/People/Berners-Lee/</uri></address></author><author initials="R." surname="Fielding" fullname="Roy T. Fielding"><organization abbrev="Day Software">Day Software</organization><address><postal><street>5251 California Ave., Suite 110</street><city>Irvine</city><region>CA</region><code>92617</code><country>USA</country></postal><phone>+1-949-679-2960</phone><facsimile>+1-949-679-2972</facsimile><email>fielding@gbiv.com</email><uri>http://roy.gbiv.com/</uri></address></author><author initials="L." surname="Masinter" fullname="Larry Masinter"><organization abbrev="Adobe Systems">Adobe Systems Incorporated</organization><address><postal><street>345 Park Ave</street><city>San Jose</city><region>CA</region><code>95110</code><country>USA</country></postal><phone>+1-408-536-3024</phone><email>LMM@acm.org</email><uri>http://larry.masinter.net/</uri></address></author><date year="2005" month="January"/><area>Applications</area><keyword>uniform resource identifier</keyword><keyword>URI</keyword><keyword>URL</keyword><keyword>URN</keyword><keyword>WWW</keyword><keyword>resource</keyword><abstract><t>A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource. This specification defines the generic URI syntax and a process for resolving URI references that might be in relative form, along with guidelines and security considerations for the use of URIs on the Internet. The URI syntax defines a grammar that is a superset of all valid URIs, allowing an implementation to parse the common components of a URI reference without knowing the scheme-specific requirements of every possible identifier. This specification does not define a generative grammar for URIs; that task is performed by the individual specifications of each URI scheme. </t></abstract></front><seriesInfo name="STD" value="66"/><seriesInfo name="RFC" value="3986"/><format type="TXT" octets="141811" target="http://www.rfc-editor.org/rfc/rfc3986.txt"/><format type="HTML" octets="214067" target="http://xml.resource.org/public/rfc/html/rfc3986.html"/><format type="XML" octets="163534" target="http://xml.resource.org/public/rfc/xml/rfc3986.xml"/></reference> <reference anchor="RFC4234"><front><title abbrev="ABNF">Augmented BNF for Syntax Specifications: ABNF</title><author fullname="Dave Crocker" initials="D." role="editor" surname="Crocker"><organization>Brandenburg InternetWorking</organization><address><postal><street>675 Spruce Dr.</street><city>Sunnyvale</city><region>CA</region><code>94086</code><country>US</country></postal><phone>+1.408.246.8253</phone><email>dcrocker@bbiw.net</email></address></author><author fullname="Paul Overell" initials="P." surname="Overell"><organization>THUS plc.</organization><address><postal><street>1/2 Berkeley Square, </street><street>99 Berkeley Street</street><city>Glasgow</city><code>G3 7HR</code><country>UK</country></postal><email>paul.overell@thus.net</email></address></author><date year="2005" month="October"/><keyword>ABNF</keyword><keyword>Augmented</keyword><keyword>Backus-Naur</keyword><keyword>Form</keyword><keyword>electronic</keyword><keyword>mail</keyword><abstract><t>Internet technical specifications often need to define a formal syntax. Over the years, a modified version of Backus-Naur Form (BNF), called Augmented BNF (ABNF), has been popular among many Internet specifications. The current specification documents ABNF. It balances compactness and simplicity, with reasonable representational power. The differences between standard BNF and ABNF involve naming rules, repetition, alternatives, order- independence, and value ranges. This specification also supplies additional rule definitions and encoding for a core lexical analyzer of the type common to several Internet specifications. </t></abstract></front><seriesInfo name="RFC" value="4234"/><format type="TXT" octets="26351" target="http://www.rfc-editor.org/rfc/rfc4234.txt"/><format type="HTML" octets="52301" target="http://xml.resource.org/public/rfc/html/rfc4234.html"/><format type="XML" octets="37285" target="http://xml.resource.org/public/rfc/xml/rfc4234.xml"/></reference> <reference anchor="RFC4648"><front><title>The Base16, Base32, and Base64 Data Encodings</title><author initials="S." surname="Josefsson" fullname="S. Josefsson"><organization/></author><date year="2006" month="October"/><abstract><t>This document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets, and canonical encodings. [STANDARDS-TRACK]</t></abstract></front><seriesInfo name="RFC" value="4648"/><format type="TXT" octets="35491" target="http://www.rfc-editor.org/rfc/rfc4648.txt"/></reference> <reference anchor="RFC5322"><front><title>Internet Message Format</title><author initials="P." surname="Resnick" fullname="Peter W. Resnick" role="editor"><organization>Qualcomm Incorporated</organization><address><postal><street>5775 Morehouse Drive</street><city>San Diego</city><region>CA</region><code>92121-1714</code><country>US</country></postal><phone>+1 858 651 4478</phone><email>presnick@qualcomm.com</email><uri>http://www.qualcomm.com/~presnick/</uri></address></author><date year="2008" month="October"/><abstract><t>This document specifies the Internet Message Format (IMF), a syntax for text messages that are sent between computer users, within the framework of "electronic mail" messages. This specification is a revision of Request For Comments (RFC) 2822, which itself superseded Request For Comments (RFC) 822, "Standard for the Format of ARPA Internet Text Messages", updating it to reflect current practice and incorporating incremental changes that were specified in other RFCs.</t></abstract></front><seriesInfo name="RFC" value="5322"/><format type="TXT" octets="122322" target="http://www.rfc-editor.org/rfc/rfc5322.txt"/><format type="HTML" octets="213393" target="http://xml.resource.org/public/rfc/html/rfc5322.html"/><format type="XML" octets="174234" target="http://xml.resource.org/public/rfc/xml/rfc5322.xml"/></reference> <reference anchor="RFC5952"><front><title>A Recommendation for IPv6 Address Text Representation</title><author initials="S." surname="Kawamura" fullname="S. Kawamura"><organization/></author><author initials="M." surname="Kawashima" fullname="M. Kawashima"><organization/></author><date year="2010" month="August"/><abstract><t>As IPv6 deployment increases, there will be a dramatic increase in the need to use IPv6 addresses in text. While the IPv6 address architecture in Section 2.2 of RFC 4291 describes a flexible model for text representation of an IPv6 address, this flexibility has been causing problems for operators, system engineers, and users. This document defines a canonical textual representation format. It does not define a format for internal storage, such as within an application or database. It is expected that the canonical format will be followed by humans and systems when representing IPv6 addresses as text, but all implementations must accept and be able to handle any legitimate RFC 4291 format. [STANDARDS-TRACK]</t></abstract></front><seriesInfo name="RFC" value="5952"/><format type="TXT" octets="26570" target="http://www.rfc-editor.org/rfc/rfc5952.txt"/></reference> <reference anchor="RFC7159"><front><title>The JavaScript Object Notation (JSON) Data Interchange Format</title><author initials="T." surname="Bray" fullname="T. Bray"><organization/></author><date year="2014" month="March"/><abstract><t>JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format. It was derived from the ECMAScript Programming Language Standard. JSON defines a small set of formatting rules for the portable representation of structured data.</t><t> This document removes inconsistencies with other specifications of JSON, repairs specification errors, and offers experience-based interoperability guidance.</t></abstract></front><seriesInfo name="RFC" value="7159"/><format type="TXT" octets="27451" target="http://www.rfc-editor.org/rfc/rfc7159.txt"/></reference> <reference anchor="JCR_ABNF" target="https://raw.githubusercontent.com/arineng/jcr/07/jcr-abnf.txt"><front><title>ABNF for JSON Content Rules</title><author fullname="Andrew Lee Newton" initials="A.L." surname="Newton"><organization abbrev="ARIN">American Registry for Internet Numbers</organization><address><postal><street>3635 Concorde Parkway</street><city>Chantilly</city><region>VA</region><country>US</country><code>20151</code></postal><email>andy@arin.net</email><uri>http://www.arin.net</uri></address></author><author fullname="Pete Cordell" initials="P." surname="Cordell"><organization>Codalogic</organization><address><postal><street>PO Box 30</street><city>Ipswich</city><country>UK</country><code>IP5 2WY</code></postal><email>pete.cordell@codalogic.com</email><uri>http://www.codalogic.com</uri></address></author><date/></front></reference></references>
<references title="Infomative References"><reference anchor="I-D.cordell-jcr-co-constraints"><front><title>Co-Constraints for JSON Content Rules</title><author initials="P" surname="Cordell" fullname="Pete Cordell"><organization/></author><author initials="A" surname="Newton" fullname="Andrew Newton"><organization/></author><date month="March" day="21" year="2016"/><abstract><t>JSON Content Rules (JCR) [JCR] provides a powerful, intuitive and concise method for defining the structure of JSON [RFC7159] messages. However, modern JSON usage patterns occasionally mean that JCR alone is not able to capture the required constraints in a satisfactory way. This document describes JCR Co-Constraints (JCRCC) which defines additional JCR directives and annotations that can be added to a JCR ruleset in order to define more detailed constraints on JSON messages.</t></abstract></front><seriesInfo name="Internet-Draft" value="draft-cordell-jcr-co-constraints-00"/><format type="TXT" target="http://www.ietf.org/internet-drafts/draft-cordell-jcr-co-constraints-00.txt"/></reference> <reference anchor="JCR_SPECIFICATION_FIGURES" target="https://github.com/arineng/jcr/tree/07/figs"><front><title>Figures in the JCR Specification</title><author fullname="Andrew Lee Newton" initials="A.L." surname="Newton"><organization abbrev="ARIN">American Registry for Internet Numbers</organization><address><postal><street>3635 Concorde Parkway</street><city>Chantilly</city><region>VA</region><country>US</country><code>20151</code></postal><email>andy@arin.net</email><uri>http://www.arin.net</uri></address></author><author fullname="Pete Cordell" initials="P." surname="Cordell"><organization>Codalogic</organization><address><postal><street>PO Box 30</street><city>Ipswich</city><country>UK</country><code>IP5 2WY</code></postal><email>pete.cordell@codalogic.com</email><uri>http://www.codalogic.com</uri></address></author><date/></front></reference><reference anchor="ARIN_JCR_VALIDATOR" target="https://github.com/arineng/jcrvalidator"><front><title>JSON Content Rules Validator (Work In Progress)</title><author><organization>American Registry for Internet Numbers</organization></author><date/></front></reference><reference anchor="CODALOGIC_JCR_VALIDATOR" target="https://github.com/codalogic/cl-jcr-parser"><front><title>cl-jcr-parser (Work In Progress)</title><author><organization>Codalogic</organization></author><date/></front></reference></references>
<section title="Co-Constraints" toc="default">
<t>This specification defines a small set of annotations and directives for JCR, yet the syntax is extensible allowing for other annotations and directives. <xref target="I-D.cordell-jcr-co-constraints" pageno="false" format="default"/> ("Co-Constraints for JCR") defines further annotations and directives which define more detailed constraints on JSON messages, including co-constraints (constraining parts of JSON message based on another part of a JSON message). </t>
</section>
<section title="Testing Against JSON Content Rules" toc="default">
<t>One aspect of JCR that differentiates it from other format schema languages are the mechanisms helpful to developers for taking a formal specification, such as that found in an RFC, and evolving it into unit tests, which are essential to producing quality protocol implementations. </t>
<section title="Locally Overriding Rules" toc="default">
<t>As mentioned in the introduction, one tool for testing would be the ability to locally override named rules. As an example, consider the following rule which defines an array of strings. </t>
<figure anchor="override1.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$statuses = [ string * ]
</artwork>
</figure>
<t>Consider the specification where this rule is found does not define the values but references an extensible list of possible values updated independently of the specification, such as in an IANA registry. </t>
<t>If a software developer desired to test a specific situation in which the array must at least contain the status "accepted", the rules from the specification could be used and the statuses rule could be explicitly overridden locally as: </t>
<figure anchor="override2.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>This rule will evaluate positively with the JSON in <xref target="override1.json" pageno="false" format="default"/> </preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$statuses = @{unordered} [ "accepted", string * ]
</artwork>
</figure>
<figure anchor="override1.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">[ "submitted", "validated", "accepted" ]
</artwork>
</figure>
<t>Alternatively, the developer may need to ensure that the status "denied" should not be present in the array: </t>
<figure anchor="override3.jcr" title="" suppress-title="false" align="left" alt="" width="" height="">
<preamble>This rule will fail to evaluate the JSON in <xref target="override2.json" pageno="false" format="default"/> thus signaling a problem. </preamble>
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">$statuses = @{unordered} @{not} [ "denied" + , string * ]
</artwork>
</figure>
<figure anchor="override2.json" title="" suppress-title="false" align="left" alt="" width="" height="">
<artwork xml:space="preserve" align="center" name="" type="" alt="" width="" height="">[ "submitted", "validated", "denied" ]
</artwork>
</figure>
</section>
<section title="Rule Callbacks" toc="default">
<t>In many testing scenarios, the evaluation of rules may become more complex than that which can be expressed in JCR, sometimes involving variables and interdependencies which can only be expressed in a programming language. </t>
<t>A JCR processor may provide a mechanism for the execution of local functions or methods based on the name of a rule being evaluated. Such a mechanism could pass to the function the data to be evaluated, and that function could return to the processor the result of evaluating the data in the function. </t>
</section>
</section>
<section title="JCR Implementations" toc="default">
<t>The following implementations, <xref target="ARIN_JCR_VALIDATOR" pageno="false" format="default"/> and <xref target="CODALOGIC_JCR_VALIDATOR" pageno="false" format="default"/> have influenced the development of this document. </t>
</section>
<section title="Syntax Changes from -06" anchor="syntax_changes" toc="default">
<t>The syntax described in this document is changed significantly, and in a non-backwards compatible manner, from the syntax described in the -06 version of this specification. The vast majority of these changes have occurred to meet the goals of the syntax being a superset of JSON and easy to comprehend by a casual reader unfamiliar with JCR but familiar with JSON. </t>
<t>The latter of those two goals is subjective, and therefore a series of focus group sessions were convened where participants, all professional software developers with familiarity with JSON but not JCR, were asked to read and interpret various rulesets and allowed to offer suggested improvements. Outcomes of these sessions resulted in many changes, such as the use of '$' characters to note rule names and the change of the repetition syntax. </t>
<t>Other changes came from feedback given directly to the authors via email and on the IETF JSON Working Group mailing list. </t>
<t>Most figures from this document can be found in file form at <xref target="JCR_SPECIFICATION_FIGURES" pageno="false" format="default"/>. </t>
</section>
</back>
</rfc>
| PAFTECH AB 2003-2026 | 2026-04-23 05:26:01 |