| Network Working Group | A. Newton |
| Internet-Draft | ARIN |
| Intended status: Standards Track | P. Cordell |
| Expires: November 18, 2019 | Codalogic |
| May 17, 2019 |
A Language for Rules Describing JSON Content
draft-newton-json-content-rules-10
This document describes a language for specifying and testing the expected content of JSON structures found in JSON-using protocols, software, and processes.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on November 18, 2019.
Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
This document describes JSON Content Rules (JCR), a language for specifying and testing the interchange of data in JSON 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.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
As a growing number of protocols use JSON, there is an increasing need to find better mechanisms to help define such protocols.
In the past, protocols often used constrained grammar strings. Such strings could be defined by example, but it was found better to use Backus-Naur Form (BNF), or variants such as ABNF. The benefit of using ABNF over examples is that the full variation of what is allowed in a protocol can be expressed in a single location. This leads to easier implementation and better interoperability.
As protocols migrate to being defined in JSON, the same need to define the valid set of JSON messages arises. It is conceivable to define the JSON-based message set by way of examples. But as with constrained grammar strings, this can be cumbersome, incomplete and easily misinterpreted, leading to the problems of implementation and interoperability mentioned earlier.
It would be theoretically possible to express the valid set of a protocol’s JSON messages using ABNF. However, ABNF is difficult to get right at the best of times, and defining an ABNF that simultaneously interwove the constraints of JSON and the constraints of the protocol into a single ABNF definition would be a task few could, or would want to, achieve. Even if it were possible, much of what was intended to describe the protocol would be obscured by the aspects describing the JSON constraints. Such an approach is likely to end up being only comprehendible by a machine and be impenetrable to humans. Therefore, arguably, such a definition would not satisfy it primary target audience.
The solution is to move up a level of abstraction. In the same way JSON is a level of abstraction above constrained grammar strings for representing protocols, a similar move up in abstraction level is needed for the mechanism used to define such protocols.
JSON Content Rules (JCR) is such a step up in abstraction. It’s relation to JSON is that of ABNF to constrained string grammars. By ‘knowing’ about JSON it can more accurately and concisely define JSON messages than other methods that are less abstracted. In the same way that abstracted languages such as Java and Python enable a programmer to work more efficiently than they can with assembler, protocol developers can work more efficiently using JCR than they can with ABNF.
That said, JCR is not the only language in this space nor the only solution, beyond ABNF, to this problem. Of the various method and languages that the authors know about, in addition to JCR, there are format translators which algorithmically convert a specification from one format to another (e.g. XML to JSON), abstraction languages such as Yang and CDDL, and at least one other JSON specific language: JSON Schema.
Format translation is an algorithmic approach to specifying protocol messages in multiple formats by using one format as the base specification and an algorithm for translating that format into another. One example would be the translation of XML into JSON using the BadgerFish algorithm and software.
This approach often creates difficult protocol messages in the destination format (i.e. JSON in the case of XML to JSON) which are hard to implement towards or debug. Additionally, while it maybe fashionable to have multiple formats, most software implementations of protocols work best with one format and often not well with others, if at all.
vCard and jCard are good examples of this. The original format and data model for vCard are specified in MIME. jCard is an algorithmic conversion of vCard to jCard. Consequently, writing software implementations of jCard requires software developers to have an intimate knowledge of MIME, saving them little in the way of time or effort.
Abstraction languages are nothing new to the schema and data definition language space, with ASN.1 being a classic example of specifying a data model in a higher-level syntax and defined algorithms for multiple data formats. ASN.1 supports many data formats, such as BER, DER, and XER (XML Encoding Rules). Yang is a more modern and popular abstraction language.
These languages have their place but suffer the same issues as format translators as they require software implementors to spend valuable energy on a syntax that is not specific to the software being implemented. Additionally, abstraction languages have, in many instances, specified features in the data model that do not translate well to all data formats or may lack compelling features because the language must cater to multiple formats.
With respect to JSON, CDDL is an abstraction language as it's data model is a superset of the data model of JSON. In other words, it is possible to specify protocol messages in CDDL that are not applicable to JSON. And because CDDL targets CBOR specifically, it does not benefit from being JSON-like, as is the case of JCR, or specified in JSON, as is the case of JSON Schema.
JSON Schema, like JCR, is a data definition language designed specifically for JSON. While JCR is more tightly scoped to defining JSON protocol messages and content, JSON Schema is more broadly scoped in its goals, including deeper aspects of data set linking and the semantic web.
JSON Schema benefits from being defined in JSON (as this makes implementations of JSON Schema tools easier), but this benefit impacts readability of specifications defining content using it. To demonstrate, the following examples define JSON using the classic example of a catalog object.
In this example, the catalog entry is defined in JSON Schema.
{ "$schema": "http://json-schema.org/draft-06/schema#", "title": "Product", "description": "A product from Acme's catalog", "type": "object", "properties": { "id": { "description": "The unique identifier for a product", "type": "integer" }, "name": { "description": "Name of the product", "type": "string" }, "price": { "type": "number", "exclusiveMinimum": 0 }, "tags": { "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true } }, "required": ["id", "name", "price"] }
Figure 1
For comparison, this example demonstrates the same catalog entry as described in Figure 1 but in JCR.
#jcr-version 0.9 ; Product – A Product for Acme’s catalog { "id" : integer, ; Unique identifier for the product "name" : string, ; Name of the product "price" : @{exclude-min} 0.0.., "tags" : [ string + ] ? }
Figure 2
The above examples demonstrate that the JCR is more concise and conveys the same information but in fewer lines in a syntax familiar with a JSON-aware software implementor.
From a high-level view point, it could be said that JSON Schema is like XML Schema whereas JCR is more like Compact RelaxNG.
Additionally, JCR syntax is a superset of JSON syntax, whereby specification authors may use example JSON protocol messages as a starting point for defining JCR rules (as is described in Section 4.1). Consequently, the effort required to turn JSON examples into JCR specifications is minimal compared to that required to create an equivalent JSON Schema. This, combined with the brevity of describing rules and the ability to name rules, allows specification authors to interleave their prose with JCR rules in their specifications, facilitating describing semantics in close proximity to syntax.
JCR's primary focus is to help specification authors concisely and clearly describe complex JSON data structures.
Being a precise, defined format reduces the potential for misunderstanding between what specification authors intended and what software developers implement.
Being a machine-readable format, the examples in a specification can be validated by the specified JCR, and it can be verified that the JCR represents the examples. This acts like unit testing in software development and has been done in the authoring of this document. (All figures used in this document are available at [FIGS].)
JCR aids software developers to verify that their implementations conform to specifications by validating any generated JSON against the specified JCR. This can be used to highlight bugs in their code or possibly identify where a specification has omissions and requires further work.
Specific examples of JCR and JSON can be included as part of conformance test vector sets to give confidence that an implementation meets a specification. JCR's ability to be specific in some locations and loose in others allows such tests to be run on a repeatable, automated basis without requiring detailed human involvement to check the results.
JCR can help resolve interoperability issues by acting as an independent arbiter between parties experiencing interoperability issues. Appealing to a JCR opinion offers the potential for a quick and cheap resolution to a disagreement. (Naturally, either party may disagree with the JCR result and take the matter further.)
Once software has been developed and deployed, JCR offers the potential for day-one in-the-field monitoring of JSON message exchanges in order to highlight conformance issues that may have slipped through the development phase.
Being a simple, defined language, JCR can also be used on an ad-hoc basis by developers as part of the design process, such as during brainstorming and whiteboarding sessions, without risking confusion over notation that may occur if an un-documented notation is used.
Being a superset of JSON syntax, those familiar with JSON will likely have an intuitive understanding of many aspects of JCR. This section offers some JCR examples to give such readers a feel for JCR before going into the detail.
The following JSON data describes a JSON object with two members, "line-count" and "word-count", each containing an integer.
{ "line-count" : 3426, "word-count" : 27886 }
Figure 3
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.
For a protocol specification, it is probably more useful to specify that each member is any integer and not specific, exact integers. Thus, a more practical JCR description would be:
{ "line-count" : integer, "word-count" : integer }
Figure 4
Since line counts and word counts should be either zero or a positive integer, the specification may be further narrowed:
{ "line-count" : 0.. , "word-count" : 0.. }
Figure 5
Building on the first example, this second example describes the same object but with the addition of another member, "file-name". An example JSON instance is:
{ "file-name" : "rfc7159.txt", "line-count" : 3426, "word-count" : 27886 }
Figure 6
The following JCR describes such objects:
{ "file-name" : string, "line-count" : 0.., "word-count" : 0.. }
Figure 7
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:
{ $fn, $lc, $wc } $fn = "file-name" : string $lc = "line-count" : 0.. $wc = "word-count" : 0..
Figure 8
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":
$fn = "file-name" : "rfc4627.txt" $lc = "line-count" : 2102 $wc = "word-count" : 16714
Figure 9
This example shows how a protocol specification can describe a JSON object in general and a test environment can override the rules for testing specific cases.
In addition to defining rules, which relate to individual JSON values, JCR also has directives, which have a more ruleset-wide effect.
Currently defined directives include "jcr-version", "ruleset-id", and "import". jcr-version specifies the version of JCR used by a ruleset and allows future versions of JCR. ruleset-id and import support combining rules from multiple rulesets.
Extending the previous example, it might be decided that the unsigned integer type associated with the $lc and $wc is so useful that it should be extracted into a ruleset of common utility types so that it can be used in other rulesets. Such a ruleset might look like:
#jcr-version 1.0 #ruleset-id com.example.common-types $count = 0..
Figure 10
As this may be a long-lived ruleset, the jcr-version directive makes it clear that JCR version 1.0 is being used. The ruleset is given the identity 'com.example.common-types' using the ruleset-id directive. The rule for the type is assigned the rule name 'count'.
A ruleset that makes use of the count type may look as follows:
#import com.example.common-types as ct { $fn, $lc, $wc } $fn = "file-name" : string $lc = "line-count" : $ct.count $wc = "word-count" : $ct.count
Figure 11
To make use of the count type it is first necessary to import the 'com.example.common-types' ruleset using the import directive. As part of the import, the 'com.example.common-types' ruleset is given an alias, 'ct', with which to refer to it. It is then possible to use the imported count type as '$ct.count'.
JCR is composed of rules (as the name suggests). A collection of rules that is processed together is a ruleset. Rulesets may also contain blank lines, comments, and directives that apply to the processing of a ruleset.
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.
A type specification is used to specify constraints on a superset of JSON values (e.g. number / string / object / array etc.). In addition to defining primitive types (such as string and integer), array and object types, type specifications may define the JCR specific concept of group types.
Type specifications corresponding to arrays, objects and groups may be composed of other rule specifications.
A member specification is used to specify constraints on members of a JSON object.
Rules that have a rule name may be referenced in place of rule specifications.
Rules may be defined across line boundaries and there is no line continuation syntax.
Any rule without a rule name is considered a root rule.  Unless otherwise specified, all the root rules of a ruleset are evaluated against a JSON instance or document.
Rule specifications may be augmented with annotations to specify additional constraints and properties. For example, arrays can be augmented with an 'unordered' annotation to indicate that the order of its members isn't significant.
The syntax for each form of type specification varies depending on the type. For example:
; primitive types include literals null ; null literal true ; boolean literal 2 ; integer literal 2.0 ; float literal "foo" ; string literal ; primitive types include ranges 1..10 ; integer range 1.0..10.00 ; float range /^[a-z]{4}$/ ; string 'range' ; primitive types can be unconstrained types boolean integer float double string ; primitive type rules may be named $my_int = 2 ; member specifications consist of a member name ; followed by a colon and followed by a ; 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 type specifications [ 1, 2, 3, $my_int ] ; finally, group specifications start and end with parenthesis ; groups contain member or type specifications ( [ integer, integer], $rule1 ) $rule1 = [ string, string ]
Figure 12
Putting it all together, the JSON in Figure 13 is described by the JCR in Figure 14.
{ "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] } }
Figure 13: Example JSON shamelessly lifted from RFC 8259
; 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
Figure 14: JCR for JSON example from RFC 8259
In addition to defining rules, JCR also has directives. These have a more ruleset-wide effect. Simple uses of JCR will likely not use directives.
This section describes each component of the JCR language in detail.
Like JSON, JCR rulesets MUST be encoded using UTF-8 unless used entirely within a private, closed ecosystem.
This document assumes that both JCR rulesets and JSON instances being processed are encoded using UTF-8. Issues related to handling JCR rulesets or JSON instances that are not encoded using UTF-8 are outside the scope of this document.
Comments are the same as comments in ABNF. They start with a semi-colon (';') and continue to the end of the line.
Blank lines are allowed. These can be used, for example, to further aid readability.
JCR uses names and identifiers to enable cross-referencing one part of a ruleset with another or from one ruleset to another. There are different types of names and different types of identifiers. For example, a local rule name is a name, and a ruleset-id is an identifier.
A name must start with an ASCII alphabetic character (a-z,A-Z) and must contain only ASCII alphabetic characters, numeric characters, the hyphen character ('-'), and the underscore character ('_'). Names are case sensitive.
An identifier must start with an ASCII alphabetic character (a-z,A-Z) and can be followed by any character other than whitespace and the closing brace ('}'). Identifiers are treated as opaque strings and therefore case-sensitive.
Directives modify the processing of a ruleset. If present, they typically appear at the start of a ruleset, before any rules are defined, but they can be placed in other parts of the ruleset if necessary. Simpler rulesets need not include any directives.
There are two forms of directive, the single line directive and the multi-line directive.
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:
# directive_name parameter_1 parameter_2 ...
Figure 15
Multi-line directives may span multiple lines. They begin with the character sequence "#{" and end with "}". They take the following form:
#{ directive_name parameter_1 parameter_2 parameter_3 ... }
Figure 16
This specification defines the directives "jcr-version", "ruleset-id", and "import", but other directives may be defined in future.
The jcr-version directive declares that the ruleset complies with a specific version of this specification. The version follows the "jcr-version" directive name and is expressed as a major integer followed by a period followed by a minor integer.
# jcr-version 0.7
Figure 17
The major.minor number signifying compliance with this document is "0.9". Upon publication of this specification it will be "1.0". [CREF1]NOTE: This will be removed in the final version.
# jcr-version 1.0
Figure 18
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. An extension identifier has the form of an identifier as described in Section 6.3. The structure of extension identifiers is specific to the extension, but it is recommended that they are terminated by a version number.
# jcr-version 1.0 +co-constraints-1.2 +jcr-doc-1.0
Figure 19
A maximum of one jcr-version directive is permitted in a ruleset. Ruleset authors are advised to place this directive as the first line of a ruleset.
The ruleset-id directive associates an identifier with a rulset. For example:
# ruleset-id http://example.com/foo
Figure 20
The identifier for the ruleset follows the "ruleset-id" directive name and has the form of an identifier as described in Section 6.3. The identifier can be a URL (e.g. http://example.com/foo), an inverted domain name (e.g. com.example.foo) or have any other internal structure that a ruleset author deems appropriate. To a JCR processor the identifier is treated as an opaque, case-sensitive string. An identifier that is URI based should not be taken to imply that the ruleset is accessible over the Internet at that address (although it is not prevented from being accessible in such a way).
A maximum of one ruleset-id directive is permitted in a ruleset. If present, it is suggested that it be the second line of a ruleset, following the jcr-version directive, or the first line if no jcr-version directive is present.
The import directive specifies that another ruleset is to have its rules evaluated in addition to the ruleset where the directive appears.
The following is an example:
# import http://example.com/rfc9999 as rfc9999 # import http://example.com/rfc9997
Figure 21
The identifier after the "import" directive name is a ruleset identifier. As such, it is an identifier as described in Section 6.3. The ruleset that is imported is identified by having the specified ruleset identifier specified in its #ruleset-id directive (See Section 6.4.2). How a JCR processor locates the imported ruleset is out of scope for this document.
The ruleset identifier may optionally be followed by the 'as' keyword that is in turn followed by an alias for the identifier. An alias has the form of a name as described in Section 6.3.
The rule names of the ruleset being imported may be referenced by combining the alias followed by a period character ('.') followed by the local rule name (i.e. "alias.name"). To continue the example above, if the ruleset identified as 'http://example.com/rfc9999' were to have a rule named 'encoding', rules in the ruleset importing it can refer to it as 'rfc9999.encoding'.
If an import directive does not specify an alias with the 'as' keyword, the local names of the imported ruleset effectively become local to the importing ruleset, except that a referenced name without an alias is sought in the importing ruleset before being sought in each of the unaliased imported rulesets.
Rules have two main components, an optional rule name assignment and a rule specification.
Rules have no statement terminator and therefore no need for a line continuation syntax. Rules may be defined across line boundaries.
A rule specification can be a type specification, a member specification or a rule name reference (see Section 6.6).
Type specifications define JSON primitive types (such as boolean, numbers, and strings), arrays, and objects. In addition to the type specifications describing JSON types, there is an additional group specification for grouping specifications.
Member specifications define members of JSON objects and are composed of a member name specification followed by either a type specification or a rule name reference to a type specification.
Rule specifications may also contain annotations which may affect the meaning of all or part of the specification.
Type specifications, depending on their type, MAY contain zero or more other rule specifications. For example, an object specification might contain multiple member specifications or rule name references that resolve to other member specifications, or a mixture of member specifications and rule name references.
For the purposes of this document, rule specifications composing other specifications are called subordinate components.
Rule specifications within arrays, objects, and groups can be defined with repetitions for specifying how many instances corresponding to the specification can appear in a JSON instance.
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 (see Section 6.7).
Rule names are used to represent rule specifications so they can be referenced elsewhere in a ruleset. A rule name can be used in two contexts; rule name assignments and rule name references.
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. If a ruleset identifier alias is present, it is separated from the local rule name by a dot character ('.'). Both ruleset identifier aliases and local rule names are types of name (see Section 6.3).
When a rule name is used in the rule name assignment context, only the local rule name part can be present. In this context, the local rule name must be unique within a ruleset (that is, no two rule name assignments may use the same local rule name in the same ruleset).
In rule name assignments, the rule name is separated from the rule specification using the '=' character.
;rule name assignments for primitive types $fuz = "fuz" $some_string = string ;rule name assignment for an array $bar = [ integer, integer, integer ]
Figure 22
In the rule name reference context, a rule name, prefixed by the dollar character ('$'), is used in place of a rule specification.
;rule name references in an object { "bar" : $bar, "foo" : $foo }
Figure 23
Ruleset identifier aliases may be included in a rule name reference. They enable referencing rules from another ruleset. Simple use cases of JCR will most likely not use ruleset identifiers.
In Figure 24 below, "http://ietf.org/rfcYYYY.JCR" and "http://ietf.org/rfcXXXX.JCR" are ruleset identifiers and "rfcXXXX" is a ruleset identifier alias. See Section 6.4.3 for details on defining and using ruleset identifier aliases.
# 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 )
Figure 24
Rule name references within a ruleset can be used either before or after their referenced rule name assignment.
Annotations may appear before a rule name assignment, before a type or member specification, or before a rule name reference. 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:
@{not} [ "fruits", "vegetables" ]
Figure 25
The @{not} annotation is described in Section 6.7.1.
The @{root} annotation is described in Section 6.18.
The @{unordered} annotation is described in Section 6.14.2.
The @{exclude-min} and @{exclude-max} annotations are described in Section 6.11.3.
The @{format} annotation is described in Section 6.11.6.
The @{choice} annotation is described in Section 6.9.1.
The @{augments} annotation is described in Section 6.19.
Other annotations may be defined for other purposes in future.
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.
; 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 * ]
Figure 26
Evaluation of subordinate components in array, object, and group specifications may be succeeded by a repetition expression denoting how many times the subordinate component may appear in a JSON instance.
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 consists of the '%' symbol followed by a positive integer.
When no repetition expression is present, both the minimum and maximum are 1.
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.
; age is optional { "name" : string, "age" : integer ? } ; zero or more errors $error_set = ( string * ) ; 1 or more integer values [ integer + ]
Figure 27
A minimum and maximum can be expressed by immediately following the '*' symbol by 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. While the minimum is optional, it is RECOMMENDED to include it even when it has a value of zero.
; 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.. ]
Figure 28
A repetition step expression may follow a minimum to maximum expression, the zero or more Kleene operator ('*'), or the one or more Kleene operator ('+').
The following is an example for repetition steps in repetition expressions:
; 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 )
Figure 29
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.
; sequence ("and") [ "this" , "that" ] ; choice ("or") [ "this" | "that" ]
Figure 30
The exact meaning of a sequence or choice depends on whether it is in an object, array or group, and they are further discussed in the relevant sections.
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:
[ "this", "that" | "the_other" ]
Figure 31
The example above should be expressed as:
[ "this", ( "that" | "the_other" ) ]
Figure 32
If an object, array or group has only zero or one items, it is ambiguous whether it is intended to be a sequence or a choice. This is an issue if the object, array or group is intended to be extended in a future version of the ruleset, especially if the mechanism for extension is the @{augments} annotation (Section 6.19).
To resolve this ambiguity, an object, array or group containing only zero or one items is treated as a sequence unless it is annotated with the @{choice} annotation, in which case it is treated as a choice.
$a_sequence_extension_point = {} $a_choice_extension_point = @{choice} {}
Figure 33
Type specifications consist of primitive specifications, objects specifications, array specifications, and group specifications. Each of these are described in the sections below.
Primitive specifications define content for JSON null, booleans, numbers, and strings.
The null type specification is the simplest and takes the following form:
null
Figure 34
A value specified to be 'null' MUST be represented in a JSON instance by the JSON 'null' value.
Type specifications for Booleans take the following forms:
true false boolean
Figure 35
A value specified to be 'true' MUST be represented in a JSON instance with the 'true' JSON value. If specified to be 'false', it MUST be represented with the 'false' JSON value. If specified to be 'boolean', it MUST be represented with either the 'true' or 'false' JSON values.
No casting or type coercion of non-Boolean types to Boolean types is permitted.
Type specifications for numbers can specify a JSON instance value to be either an integer or floating point number. For example:
integer float double 10 10.0 0..10 0.0..10.0 uint32
Figure 36
The keyword 'integer' specifies a signed integer value of arbitrary size.
The keyword 'float' represents a single precision IEEE-754 floating point number [IEEE754] represented in decimal format. The keyword 'double' represents a double precision IEEE-754 floating point number represented in decimal format.
Numbers may also be specified as specific values or a range of possible values, where a range may be specified using a minimum, maximum, or both.
To specify a specific value, the value itself is specified. Note that floating point types MUST include a fractional or exponent part, even if the fractional part is zero.
10 ; specifies the exact integer value 10 10.0 ; specifies the exact floating point value 10
Figure 37
To specify a range, the range token, consisting of two consecutive dot characters ('..'), is used. The minimum in the range, if present, is placed before the range token, and the maximum, if present, is placed after the range token (with no intervening spaces). If the minimum is absent, that specifies no lower bound. If the maximum is absent, it specifies no upper bound.
10..100 ..100 10.. 10.5..100.5 ..100.5 10.5..
Figure 38
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:
0.0..10.0
Figure 39
When a range is used to define a number, by default the minimum and maximum values are included in the range. The @{min-exclusive} annotation can be specified to exclude the minimum from the range, and the @{max-exclusive} annotation can be specified to exclude the maximum from the range.
$greater-than-or-equal-to-10 = 10.0.. $greater-than-10 = @{min-exclusive} 10.0.. $less-than-or-equal-to-100 = ..100.0 $less-than-100 = @{max-exclusive} ..100.0 $gt-10-lt-100 = @{min-exclusive} @{max-exclusive} 10.0..100.0
Figure 40
The range of integers may also be specified using bit lengths. The type specification is constructed with a prefix followed by a number. The prefix 'int' specifies a signed integer, and the prefix 'uint' specifies an unsigned integer. The number that follows is a positive integer that specifies the number of bits in the integer. For signed integers, the bit length is based on the two's complement integer format.
; 0..255 uint8 ; -32768..32767 int16 ; 0..65535 uint16 ; –9223372036854775808..9223372036854775807 int64 ; 0..18446744073709551615 uint64
Figure 41
When specifying numbers, ruleset authors are recommended to bear in mind the commentary on numbers in [RFC7493].
A value specified to be a number MUST be represented in an instance as a JSON number. Strings containing character sequences representing numbers MUST NOT be treated as numbers.
If a range is specified for a number, the JSON instance value MUST satisfy the specified range.
It is preferred that a JSON instance value specified to be an integer does NOT include a fractional part (as specified by the frac rule in the ABNF) or an exponential part (as specified by exp in the ABNF). This preferred behaviour can not be mandated because JCR defined messages are intended to be used with generic JSON generators. The following shows preferred, non-preferred and invalid representations of integer instance values:
50 ; Preferred integer format 50.0 ; Non-preferred integer format 5e1 ; Non-preferred integer format "50" ; Not an integer
Figure 42
An unconstrained string may be specified using the keyword 'string'. String literals may be specified using a double quote character followed by the literal content followed by another double quote. Regular expressions can specify constrained strings by enclosing a regular expression within forward slash ('/') characters.
; any string string ; a string literal "she sells sea shells" ; a regular expression /^she sells .*/
Figure 43
Regular expressions are not implicitly anchored and therefore must be explicitly anchored if necessary.
Regular expressions SHOULD use the ECMA 262 dialect used by JavaScript. This is mostly a sub-set of the common regular expression dialects, and any regular expression thus defined, after converting escape sequences to UTF-8, should be usable in any mainstream regular expression engine.
A value specified to be a string MUST be represented in a JSON instance as a JSON string value.
To validate a literal string specification, escape sequences in both the JCR string specification and the JSON instance value are converted to UTF-8. The two strings are then compared as opaque sequences of bytes and MUST be identical for the JSON instance value to be considered valid. They are thus treated as case-sensitive. No whitespace processing or Unicode normalization is performed. For the literal string specification "JCR Rules", both JSON instance values of "JCR Rules" and "\u004ACR Rules" are valid, while the JSON instance values "jcr rules", " JCR Rules ", or "JCR Rules" are invalid.
To be valid against a regex string specification, a JSON instance value, after converting escape sequences to UTF-8, MUST satisfy the specified regular expression.
JCR provides a large number of data types beyond those defined by JSON. They are encoded in JSON instances using JSON strings.
A string can be specified to be a URI using the keyword 'uri', but also may be more narrowly scoped to a URI of a specific scheme. Specific URI schemes are specified with the keyword 'uri' followed by two period characters ('..') followed by the URI scheme.
; any URI uri ;a URI narrowed for an HTTPS uri uri..https
Figure 44
IP addresses may be specified with either the keyword 'ipv4' for IPv4 addresses or the keyword 'ipv6' for IPv6 addresses. Fully qualified A-label and U-label domain names may be specified with the keywords 'fqdn' and 'idn'.
Dates and times can be specified as formats found in RFC 3339. The keyword 'date' corresponds to the full-date ABNF rule, the keyword 'time' corresponds to the full-time ABNF rule, and the keyword 'datetime' corresponds to the date-time ABNF rule.
Email addresses formatted according to RFC 5322 may be specified using the 'email' keyword, and E.123 phone numbers may be specified using the keyword 'phone'.
;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
Figure 45
Binary data can be specified in string form using the encodings specified in RFC 4648. The keyword 'hex' corresponds to base16, while 'base32', 'base32hex', 'base64', and 'base64url' correspond with their RFC 4648 counterparts accordingly.
; RFC 4648 base16 hex ; RFC 4648 base32 base32 ; RFC 4648 base32hex base32hex ; RFC 4648 base64 base64 ; RFC 4648 base64url base64url
Figure 46
A value specified to be a semantic string MUST be represented in a JSON instance as a JSON string value and MUST satisfy all the constraints specified by the relevant standard(s) for the semantic type.
New types will likely be added as a form of JSON string. Some such formats may have structure that can't easily be represented using regular expressions and other such techniques.
To address this a @{format} annotation is used. This annotation contains a uri identifying the format of the string being defined.
For example, a fictional JCR ruleset specifying a DNA fingerprint type might be:
# ruleset-id http://bio.example.org/specs/dna $fingerprint = @{format http://bio.example.org/specs/dna#fingerprint} string
Figure 47
From a validators perspective, the above type could be considered to be a 'string with the format specified by http://bio.example.org/specs/dna#fingerprint'.
The method used to define the structure of the string is beyond the scope of this document. It could use regular expressions, ABNF, narrative text or some other method.
The uri is an abstract resource identifier. Whether it is resolvable to a descriptive document or not is beyond the scope of this document.
Whether validators give errors, warnings or act silently when they encounter a spec uri they don't know is an implementation detail.
Member specifications define members of JSON objects. Unlike type specifications, member specifications cannot be root rules and must be part of an object specification, a group specification, or preceded by a rule name assignment.
Member specifications consist of a member name specification followed by optional whitespace followed by a colon character (':') followed by optional whitespace followed by either a rule name reference or a type specification. Member name specifications can be given either as a quoted string delimited by double quotes or as a regular expression delimited by forward slash ('/') characters. Regular expressions are not implicitly anchored and therefore must have explicit anchors if needed.
;member name will exactly match "locationURI" $location_uri = "locationURI" : uri ;member name will match "eth0", "eth1", ... "eth9" $iface_mappings = /^eth[0-9]$/ : ipv4
Figure 48
Member specification validation takes place as part of object validation, which is described in Section 6.13.
Object specifications define the permitted contents of JSON objects and are composed of zero or more subordinate components, each of which can be either a rule name reference, 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 ('}').
Subordinate components MAY have repetitions as described in Section 6.8 and MAY be combined into sequences and/or choices as described in Section 6.9.
The following examples illustrate matching of JSON object instances to JCR object specifications.
The order of member specifications in a object specification does not dictate the order of member instances in a JSON object instance. The following object specification will match the object instances in both Figure 50 and Figure 51.
{ "locationUri" : uri, "statusCode" : integer }
Figure 49
{ "locationUri" : "http://example.com", "statusCode" : 200 }
Figure 50
{ "statusCode" : 200, "locationUri" : "http://example.com" }
Figure 51
Before a JSON instance can be validated, it is necessary to associate JSON object instance members with JCR member specifications. This is performed as follows:
There are 3 types of member name specification: q-string specs, (non-empty) regex specs, and the (empty regex) wildcard spec. (e.g. "foo", /^foo/ and //.)
All name specifications within an object specification are divided into these three groups (q-string spec, regex spec, and wildcard spec). (Note that the same name specification may appear multiple times within an object specification, typically in different groups.)
Each instance member name is first tested for a match against the q-string spec name specifications. If the instance name is matched, the instance name and its value is associated with every occurrence of that name specification and its type(s).
If an instance name does not match a q-string spec name specifications, then it is tested for a match against the regex spec name specifications. If the instance name matches a single regex spec, the instance name and its value is associated with every occurrence of that name specification and its type(s). If the instance name matches more than one regex spec, the JSON instance is considered to be invalid.
If an instance name does not match either a q-string spec or regex spec name specification and a wildcard spec name specification is present, then the instance name and its value is associated with every occurrence of the wildcard specification and its type(s).
If an instance name does not match either a q-string spec or regex spec name specification and there is no wildcard spec name specification present, then the instance name and its value is ignored.
The above rules mean that any instance name can only be associated with one name specification (although multiple instances of that name specification may appear with an object specification). As a result, both of the object specifications below are equivalent:
$o1 = { /^p\d+$/ : integer *, "p1" : string } $o2 = { "p1" : string, /^p\d+$/ : integer * }
Figure 52
The following JSON instance is valid against both of the above object specifications:
{ "p0" : 1, "p1" : "a string" }
Figure 53
It is important to be able to determine whether a JSON instance is valid against a JCR specification irrespective of whether it is a human or machine performing the assessment.
Validation of object instances against object specifications takes place as follows:
As stated above, members of instance objects that are not associated with a member name specification 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.
However, some specifications may need to restrict the members of a JSON object to a known set. To construct a specification specifying that no extra members are allowed, the @{not} annotation (see Section 6.7.1) may be used with a "match-all" regular expression as the last subordinate component of the object specification.
The following rule will match the JSON object in Figure 55 but will not match the JSON object in Figure 56.
{ "foo" : 1, "bar" : 2, // : any *0 }
Figure 54
{ "foo" : 1, "bar" : 2 }
Figure 55
{ "foo" : 1, "bar" : 2, "baz" : 3 }
Figure 56
This works because the last specification is associated with any member instances that are not associated with a prior specification. As such, no member instance is ignored. But, due to the *0 repetition specification, the object fails to validate if one or more of those instances are present.
Object rule name references 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 below, both obj1 and obj2 have members "foo" and "fob" with obj1 having the additional member "bar" and obj2 having the additional member "baz".
$mixin_object = { "foo" : integer, "fob" : uri } $obj1 = { $mixin_object, "bar" : string } $obj2 = { $mixin_object, "baz" : string }
Figure 57
Group rules may also be used to create object mixins (See Section 6.17.2.)
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 (']').
As with object specifications, array subordinate components MAY have repetitions as described in Section 6.8 and MAY be combined into sequences and/or choices as described in Section 6.9.
Arrays can be specified as either ordered or unordered. Arrays are ordered by default.
In an ordered array specification, unlike object specifications, the order of type specifications dictates the permitted order of array instance values.
Evaluation of the subordinate components of ordered array specifications is as follows:
Take for example the following ruleset:
; 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 ]
Figure 58
It defines two rules, a1 and a2. The array in the following JSON will not match a1, but will match a2.
[ 24, "Bob Smurd" ]
Figure 59
If an array instance has more elements than can be matched from the array specification, the array instance does not validate against 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:
[ 24, "Bob Smurd", "http://example.com/bob_smurd" ]
Figure 60
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:
; 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 * ]
The JSON array in Figure 60 will validate against the a3 rule in this example.
Figure 61
Validating an ordered array, in the general case, has similarities with matching a regular expression or an ABNF grammar.  For example, the following JCR specification:
[ $first_name, $middle_name ?, $last_name, $birth_year ] $first_name = string $middle_name = string $last_name = string $birth_year = integer
Figure 62
should accept the JSON instance:
[ "George", "Washington", 1732 ]
Figure 63
When validating the above instance, a validator may initially associate "George" with $first_name and "Washington" with $middle_name. It will then attempt to validate 1732 against $last_name, which will fail. At this point, recognizing that $middle_name is optional, the validator must back-track and associate "Washington" with $last_name. From there it can validate 1732 with $birth_year and yield that the instance is valid.
Similarly, the following JCR:
[ string, ( string | integer ) ?, string ]
Figure 64
permits each of the following JSON instances:
[ "A", "B", "C" ] [ "A", 1, "C" ] [ "A", "C" ]
Figure 65
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.
In the ruleset below, a1 and a2 have the same subordinate components given in the same order. a2 is annotated with the @{unordered} annotation.
$a1 = [ string, integer ] $a2 = @{unordered} [ string, integer ]
Figure 66
The JSON array below does not match a1 but does match a2.
[ 24, "Bob Smurd" ]
Figure 67
The @{unordered} annotation can only be applied to an array as a whole. It can not be applied to groups within an array.
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.
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.
A type specification can be a type choice. A type choice begins with an opening parenthesis ('(') and ends with a closing parenthesis (')'). Its subordinate components are type specifications or rule name references combined using the choice combiner as described in Section 6.9.
{ "age" : (0.. | "unknown") }
Figure 68
Type choices can also be used for enumerations.
{ "status" : ("open" | "closed" | "unknown" | string) } ; string included to allow for future extension
Figure 69
To validate against a type choice, an instance value MUST validate against one (or more) of the subordinate component type specifications.
The 'any' type specifies that a JSON value instance can be any primitive type, array type, or object type.
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 ('(') & (')').
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 referenced. For example, a group specification referenced inside of an array specification may not contain a member specification since member specifications are not allowed as direct subordinate components 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). A group specification may also represent a type choice (See Section 6.15).
As with object and array specifications, group subordinate components MAY have repetitions as described in Section 6.8 and MAY be combined into sequences and/or choices as described in Section 6.9.
The following is an example of two group specifications that are referenced by an array specification:
$parents = ( "Mike", "Carol" ) $children = ( "Greg", "Marsha", "Bobby", "Jan" ) $the_bradys = [ $parents, $children ]
Figure 70
Group specifications are not validated against JSON instances by themselves. During validation of objects, arrays or type choices, references to group specifications are replaced with their referenced content. For example, the the_bradys rule in Figure 70 is validated as if it were:
$the_bradys = [ "Mike", "Carol", "Greg", "Marsha", "Bobby", "Jan" ]
Figure 71
Groups may be a subordinate component of array specifications:
[ ( ipv4 | ipv6 ), integer ]
Figure 72
Unlike primitive specifications, subordinate group specifications in array specifications may have sequence combinations and contain any type specification.
; 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..
Figure 73
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.
; 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
Figure 74
The syntax for group specifications accommodates one or 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.
$paragraphs = ( /^p[0-9]*$/ : string + )
Figure 75
This differs from a member specification because it includes a repetition specification.
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.
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.
The "@{root}" annotation may either appear before a rule name assignment or before a type definition. It is an error if present before referenced rule name inside of a type specification.
@{root} $request = { "cmd" : string } $response = @{root} { "reply" : string } @{root} { "status" : string } { "error" : string } ; An implicit root
Figure 76
IETF protocols often specify a core protocol and then additional functionality is added over time by defining additional specifications that update the original core protocol. The @{augments} annotation supports this way of working.
Typically objects, arrays and groups will include rule name references that reference child rules. The @{augments} annotation allows the direction of that referencing to be reversed. It effectively allows a child rule to specify that a parent rule should be augmented with a rule name reference to itself (the child).
The parameters of the @{augments} annotation consist of one or more, space-separated rule name references to parent rules that should be augmented with the name of the rule that has the @{augments} annotation.
For example, the following rules:
$main = { "first" : integer } $extension = @{augments $main} ( "extra" : string ? )
Figure 77
is equivalent to the following:
$main = { "first" : integer, $extension } $extension = ( "extra" : string ? )
Figure 78
Note that the reverse linking can occur across multiple rulesets with different ruleset-ids. For example, an extension might be defined as:
#ruleset-id org.example.extension #import org.example.core as core $extension = @{augments $core.main} ( "extra" : string ? )
Figure 79
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:
{ // : string }
Figure 80
The JSON below matches the above rule.
{ "foo" : "bar" }
Figure 81
Likewise, the JSON below also matches the same rule.
{ "fuzz" : "bazz" }
Figure 82
Constructing an object with a member of any name with any type would therefore take the form:
{ // : any }
Figure 83
The above rule matches not only the two JSON objects above, but the JSON object below.
{ "fuzz" : 1234 }
Figure 84
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.
Consider the following examples:
; either an IPv4 or IPv6 address $address = ( ipv4 | ipv6 ) ; allowable fruits $fruits = ( "apple" | "banana" | "pear" )
Figure 85
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.
In the following example, the referrer_uri member can only be present if the location_uri member is present.
; $referrer_uri can only be present if ; $location_uri is present { ( $location_uri, $referrer_uri? )? } $location_uri = "locationURI" : uri $referrer_uri = "referrerURI" : uri
Figure 86
For validation, the above optional group is equivalent to:
{ ( $location_uri, $referrer_uri? ) | () }
Figure 87
JCR has evolved since its initial conception. Often this has been as a result of 'in-the-field' experience. As JCR has evolved, certain features have been discarded from the main specification, but should still be supported by implementations in order not to break environments where JCR is already deployed. This section lists these deprecated features.
For legacy support, rule name assignments to primitive type specifications may optionally use the character sequence '=:', or the token sequence '= type', instead of a single '=' character.
;rule name assignments for primitive types ;using the legacy =: and = type syntax $foo =: "foo" $other_string = type string
Figure 88
This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in [RFC7942]. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist.
According to [RFC7942], "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit".
The JCR Validator, written in Ruby, currently implements all portions of this specification, and has been used extensively to prototype various aspects of JCR under consideration. Its development has gone hand-in-hand with this specification.
This software is primarily produced by the American Registry for Internet Numbers (ARIN) and freely distributable under the ISC license.
Source code for this software is available on GitHub at [JCRVALIDATOR]. This software is also easily obtained as a Ruby Gem through the Ruby Gem system.
The Codalogic JCR Parser is a C++ implementation of a JCR parsing engine, and is a work in progress. It is targeted for the Windows platform.
This software is produced by Codalogic Ltd and freely distributable under the Gnu LGPL v3 license.
Source code is available on GitHub at [CLJCR].
JCR Java is a work in progress and currently only implements the parsing of JCR rulesets according to the ABNF using a custom parsing framework.
This software is produced by the American Registry for Internet Numbers (ARIN) and freely distributable under the MIT license.
Source code is available on BitBucket at [JCRJAVA].
The following ABNF describes the syntax for JSON Content Rules. A text file containing these ABNF rules can be downloaded from [JCR_ABNF].
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 = id id = ALPHA *id-tail id-tail = %x21-7C / %x7E-10FFFF ; not spaces, not } 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 = id 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 / value-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 ) ")" 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 / exclude-min-annotation / exclude-max-annotation / default-annotation / format-annotation / choice-annotation / augments-annotation / tbd-annotation not-annotation = not-kw unordered-annotation = unordered-kw root-annotation = root-kw exclude-min-annotation = exclude-min-kw exclude-max-annotation = exclude-max-kw default-annotation = default-kw spaces primitive-value primitive-value = false-value / null-type / true-value / float-value / integer-value / string-value format-annotation = format-kw spaces id choice-annotation = choice-kw augments-annotation = augments-kw *(spaces target-rule-name) 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 [ 1*( sequence-combiner object-item ) / 1*( choice-combiner object-item ) ] object-item = object-item-types *sp-cmt [ repetition *sp-cmt ] object-item-types = object-group / member-rule / target-rule-name object-group = annotations "(" *sp-cmt [ object-items *sp-cmt ] ")" array-rule = annotations "[" *sp-cmt [ array-items *sp-cmt ] "]" array-items = array-item [ 1*( sequence-combiner array-item ) / 1*( choice-combiner array-item ) ] array-item = array-item-types *sp-cmt [ repetition *sp-cmt ] array-item-types = array-group / type-rule array-group = annotations "(" *sp-cmt [ array-items *sp-cmt ] ")" group-rule = annotations "(" *sp-cmt [ group-items *sp-cmt ] ")" group-items = group-item [ 1*( sequence-combiner group-item ) / 1*( choice-combiner group-item ) ] group-item = group-item-types *sp-cmt [ repetition *sp-cmt ] group-item-types = group-group / member-rule / type-rule group-group = group-rule sequence-combiner = "," *sp-cmt choice-combiner = "|" *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 re-escape-code / not-slash ) "/" [ regex-modifiers ] re-escape-code = %x20-7F ; Specific codes listed elsewhere 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" augments-kw = %x<IP_ADDRESS>D.65.6E.74.73 ; "augments" base32-kw = %x<IP_ADDRESS>.33.32 ; "base32" base32hex-kw = %x<IP_ADDRESS>.<IP_ADDRESS>.78 ; "base32hex" base64-kw = %x<IP_ADDRESS>.36.34 ; "base64" base64url-kw = %x<IP_ADDRESS>.<IP_ADDRESS>.6C ; "base64url" boolean-kw = %x62.6F.6F.6C.65.61.6E ; "boolean" choice-kw = %x63.68.6F.69.63.65 ; "choice" date-kw = %x<IP_ADDRESS> ; "date" datetime-kw = %x<IP_ADDRESS>.74.69.6D.65 ; "datetime" default-kw = %x<IP_ADDRESS>.75.6C.74 ; "default" double-kw = %x64.6F.75.62.6C.65 ; "double" email-kw = %x65.6D.61.69.6C ; "email" exclude-max-kw = %x<IP_ADDRESS>C.<IP_ADDRESS>D.6D.61.78 ; "exclude-max" exclude-min-kw = %x<IP_ADDRESS>C.<IP_ADDRESS>D.6D.69.6E ; "exclude-min" false-kw = %x66.61.6C.73.65 ; "false" float-kw = %x66.6C.6F.61.74 ; "float" format-kw = %x66.6F.72.6D.61.74 ; "format" fqdn-kw = %x<IP_ADDRESS>E ; "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.<IP_ADDRESS>.72 ; "integer" ipaddr-kw = %x<IP_ADDRESS>.64.72 ; "ipaddr" ipv4-kw = %x<IP_ADDRESS> ; "ipv4" ipv6-kw = %x<IP_ADDRESS> ; "ipv6" jcr-version-kw = %x6A.63.72.2D.<IP_ADDRESS>.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.<IP_ADDRESS>.2D.69.64 ; "ruleset-id" string-kw = %x<IP_ADDRESS>.6E.67 ; "string" time-kw = %x74.69.6D.65 ; "time" true-kw = %x<IP_ADDRESS> ; "true" type-kw = %x<IP_ADDRESS> ; "type" uint-kw = %x75.69.6E.74 ; "uint" unordered-kw = %x75.6E.6F.<IP_ADDRESS>.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
Figure 89: ABNF for JSON Content Rules
The usage scenarios of JCR parallel that of ABNF. As such, when used in protocol specification, software development and test contexts, JCR should not present any security issues.
If JCR is used for validation in production environments, implementors are advised not to download rulesets on-the-fly, as this offers an additional attack vector for hackers, which could allow invalid JSON to be accepted as valid.
John Cowan, Andrew Biggs, Paul Kyzivat and Paul Jones provided feedback and suggestions which led to many changes in the syntax.
| [I-D.cordell-jcr-co-constraints] | Cordell, P. and A. Newton, "Co-Constraints for JSON Content Rules", Internet-Draft draft-cordell-jcr-co-constraints-00, March 2016. |
| [RFC7493] | Bray, T., "The I-JSON Message Format", RFC 7493, DOI 10.17487/RFC7493, March 2015. |
| [RFC7942] | Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, July 2016. |
| [CLJCR] | "Codalogic JCR Parser" |
| [FIGS] | "JCR Document Figures" |
| [JCRJAVA] | "JCR Java" |
| [JCRVALIDATOR] | "JCR Validator" |
The following features are in development and may appear in a future version of this specification.
Augmented OR of objects is an algorithm for better writing of OR, where the current approach uses simple inclusive OR. The design goal behind augmented OR is to give the writer and the reader a "that's what I meant" solution.
For example, take the following rule for an object where two members are given as a choice.
{ "foo":string | "bar":integer }
Figure 90
The interpretation of Figure 90 is that the object may either contain a member named "foo" that is a string or a member named "bar" that is an integer. To some, that raises a number of questions:
With normal inclusive OR, it might be necessary to write more complicated rules to disambiguate the desired contents of the object, as this rule demonstrates.
{ ( "foo":string , @{not} "bar":any ) | ( "bar":integer, @{not} "foo":any ) }
Figure 91
The augmented OR algorithm for objects would allow Figure 90 to mean the equivalent as the Figure 91 using inclusive OR.
JCR is intentionally designed with a rich set of data types to eas the burden of reading and writing rules.
The following are a list of new data types under consideration:
JCR can be extended through the use of annotation but also has a set of standard annotations. The design philosophy for annotations are to provide features to the language that are not as common or do not have a clear, less-wordy syntax.
The following annotations are under consideration:
This specification defines a small set of annotations and directives for JCR, yet the syntax is extensible allowing for other annotations and directives. [I-D.cordell-jcr-co-constraints] ("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).
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.
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.
$statuses = [ string * ]
Figure 92
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.
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:
This rule will evaluate positively with the JSON in Figure 94
$statuses = @{unordered} [ "accepted", string * ]
Figure 93
[ "submitted", "validated", "accepted" ]
Figure 94
Alternatively, the developer may need to ensure that the status "denied" should not be present in the array:
This rule will fail to evaluate the JSON in Figure 96 thus signaling a problem.
$statuses = @{unordered} @{not} [ "denied" + , string * ]
Figure 95
[ "submitted", "validated", "denied" ]
Figure 96
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.
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.
The syntax of JCR was changed so that rule name assignments to primitive types no longer requires the '=:' syntax. The '=:' is still provided for backwards compatibility. Other syntax changes have been made to accommodate the syntax of future annotations.


UK Conservatives hold 16-point lead over Labour: Ipsos MORI/Evening Standard poll
LONDON (Reuters) - British Prime Minister Boris Johnson’s Conservative Party holds a 16-point lead over the opposition Labour Party three weeks ahead of the Dec. 12 general election, according to an Ipsos MORI poll for the Evening Standard newspaper.
The Conservatives and Labour are sucking support from the Liberal Democrats and the Brexit Party, the poll showed.
Support for the Conservatives stood at 44%, up 3 points from last week’s poll, and that for Labour was up four points at 28%.


Every year the AIAA Foundation with assistance from several AIAA Technical Committees and corporate sponsors Cessna Aircraft Company and Raytheon Missile Systems, sponsors a competition for undergraduate and graduate students to design and build a remote-controlled aircraft to perform specific tasks. Students then come together to face off against each other in April. Started in 1996 by the AIAA Applied Aerodynamics, Aircraft Design and Flight Test Technical Committees as an opportunity for university students to apply real-world aircraft design experience by giving them the opportunity to validate their analytic studies. Student teams design, fabricate, and demonstrate the flight capabilities of an unmanned, electric powered, radio-controlled aircraft which can best meet the specified mission profile. The goal is a balanced design possessing good demonstrated flight handling qualities and practical and affordable manufacturing requirements while providing a high vehicle performance.


The Thrill Killers (1964) 69m.
After force-feeding my brain RAT PFINK A BOO BOO, I'd pledged never again to watch any film by Z-grade writer-director-actor Ray Dennis Steckler. But I was surprised to find THE THRILL KILLERS a much more tightly-made piece of work. As it stands, it's probably Steckler's best film, though admittedly that isn't saying a lot. Tightly edited, with a jazzy score and some involving sequences, it's a cut above most other Z-features, but also shares their pitfalls. Story basically recounts the encounters between psychotics and anyone unfortunate enough to run into them, providing Stecker with an excuse to string together a number of set pieces. Its main problem is that characters belong to different stories - it's like Steckler started filming four different projects and then decided to put them all together for the last half. At the start we're not even sure who the main character is supposed to be, or how other characters are meant to relate to each other.
THE THRILL KILLERS' best feature is that it's wonderfully unpredictable, although this may be a natural consequence of Steckler's seemingly undisciplined approach. He doesn't play by the rules of conventional movies and doesn't guarantee the safety of any of the characters. This results in some inspired, demented moments. My favorite is when one psycho makes a phone call to an even more psychotic acquaintance, asking for help to get away from his 'crazy' friends! Steckler isn't really playing for laughs, though. In fact much of the violence, though offscreen, is unsettling (Steckler himself is well cast as thug 'Mad Dog' Glick). As a one-man show, Steckler has talent (next to Z-grade alumnus Herschell Gordon Lewis, he's Orson Welles), but it is uneven. It would have been interesting to see what he would have done if contracted by a studio with a bigger budget - I believe this could have been regarded as a classic B-feature if it had been made with more experienced actors and writers. If you've never seen a film by an indie director before, have a look. Just don't spend more than a dollar on it.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


ESS-NW-CAR
Embedded Self-adaptive Services
Class Hierarchy
Go to the textual class hierarchy
Generated by
1.8.13


/ffz promote <id>
with the appropriate message id. The easiest
way to do this is to add a custom in-line moderation icon with the command
/ffz promote {id}
replaces
field to emoticons to allow extension emotes to replace Twitch emotes.Chat Appearance > Enable Custom Badge Images
setting that can be used to disable custom mod badges for channels.Chat Appearance > Old-Style Subscriber Notices
enabled.room-recent-highlights
event even if the Recent Highlights feature is disabled.room-recent-highlights
event for triggering behaviors when new highlighted messages are displayed.room-message
API event.AUTOMOD_SMALLER
experiment. In-Line AutoMod is not yet working when you are part of that experiment.user-emotes
service in all places since tmiSession
's emote parser has been removed.Chat Filtering > Remove Messages from Moderators
.Reset Player
button directly at the bottom of the player since positioning it in the menu would require a mutation observer now that the player UI is powered by React.User (undefined)
in tab completion.error
method not accepting an optional object to log.localStorage.hasOwnProperty
due to a Chrome bug.Channel: undefined
for emoticons from unknown sets. They might not be from a channel, and it looks bad.system-msg
tags that contain template strings or other nonsense that Twitch, for some reason, isn't just putting in the message itself and is making the client reconstruct from tags.has_prefix
for emote sets and prefix_length
for emote sets and emotes.game
bttv-room-message
event for awareness of chat messages sent when BetterTTV is installed. This data structure is not like standard room-message
.user_add_badge
and room_add_user_badge
now support complex badge structures rather than just IDs for more flexible badge setups./reset
command which clears the current Top Cheer.api.retokenize_messages
didn't actually work.:before
pseudo-elements.api.retokenize_messages(room, user, max_age)
now takes a maximum age to prevent it from processing old chat messages./followers
and /followersoff
as they can be used even if you don't have the tab enabling the UI.api.retokenize_messages
to force retokenization of old chat messages after emoticons load.?standalone
to the end of the URL for your dashboard to see it. (Thanks to Warchamp7 for this idea.)/me>
.api.register_metadata
and api.unregister_metadata
functions for registering custom channel metadata providers./renamegroup
chat command to rename the current group chat room./card
command and the link in whisper windows to Open Moderation Card were not working.api.room_add_user_badge
and api.room_remove_user_badge
methods for adding and removing room-specific badges from a user. Note: These methods only function when the associated room is loaded.@
) followed by usernames are clickable. Localized display names will not work.)name_key
rather than id
for badges added through the API to give them predictable classes.name_key
parameter to API constructor.chat-view-init
and chat-view-destroy
events for adding event handlers to chat.api.iterate_chat_views
method to be used during initialization to call the chat-view-init
events for already existing chat views.sort
property for emote sets for sorting the My Emoticons menu.source_line
property for emote sets to further customize the source displayed in emoticon tooltips.no_tooltip
property for badges to avoid adding the default tooltip behavior.target-msg-id
when users are banned.Add Friend
buttons when friends are disabled.isLoading
function. (Presumably because the player doesn't break if you try using it while it's loading, now.)/untimeout
support.view:room
with component:chat/chat-room
which broke several features. Unbroke them.modifier
flags were not being accepted.Object.assign
.api.on(event, callback)
, api.off(event, callback)
, and api.trigger(event, args...)
initialized
, bttv-initialized
, room-add
, room-remove
, room-message
api.iterate_rooms(function(room_id) { })
to call a function for every current chat room.register_chat_filter
, unregister_chat_filter
, register_on_room_callback
, and unregister_on_room_callback
fetch
.>deleted link<
when they shouldn't."null"
if they didn't have high-DPI images causing them to render as a blank for some users.--prime--
in FFZ's emote tooltips.-webkit-mask
property.hasSystemMsg
property as systemMsg
will always contain a string now.Hidden Badges
setting to make it more obvious how to hide any given badge when the names don't quite lien up.Free with Prime
from the sidebar.hidden
property for emote sets to keep them out of the emote menu./rules
chat command to show the chat rules for a room./open_link
chat command for use with moderation actions./fetch_link
chat command for user with moderation actions.undefined
in chat under certain situations./ffz following
.Deprecated
and not Depreciated
.NaN
for group chats.hasOwnProperty
, which is a JavaScript function named and it broke things slightly.current_bitrate
if the more accurate player stat is not available.getVideoInfo
function as the new HTML5 player now exposes playback statistics.getVideoInfo
, FFZ will parse stats from the overlay that shows on-stream.playback_bytes_per_second
to calculate the current bitrate, as the other bitrate statistics don't update properly.model:stream
to model:deprecated-stream
which broke the following count in the sidebar.overflow: hidden
to chat lines to hide Zalgo text.{id}
in Custom In-Line Moderation Icons to insert the message ID into the command.model:channel
has been renamed to model:deprecated-channel
.float
when rendering chat.background-size
was not specified.api.add_badge(badge_id, badge)
, api.remove_badge(badge_id)
, api.user_add_badge(username, slot, badge_id)
, and api.user_remove_badge(username, slot)
to allow other extensions to more easilly add and remove badges to FFZ.shouldRenderMessageBody
property.Infinity:NaN:NaN
which... while kinda true, isn't really helpful?controller:layout
and controller:login
to be service:
s instead, which broke several FFZ features and prevented FFZ from detecting that a user was logged in. This has been fixed./emoteonly
when we know it's enabled on a room./ffz reload
command had a bug preventing it from completing and showing output to the user.document.body
exists, apparently.More at Twitch
in the sidebar.api.user_add_set(user_name, set_id)
and api.user_remove_set(user_name, set_id)
to manage a user's emoticon sets.api.register_chat_filter(filter)
to allow APIs to pre-filter chat messages.(Chat Paused Due to Mouse Movement)
warning is no longer visible over chat./ffz reload
erroring.watch
, unwatch
, and constructor
..admin
instead of .notification
to style sub notices, like a silly person.ffz.settings.set("dev_html5_player", true)
box-sizing: border-box
by Twitch./card <username>
command to open a moderation card for any user without having to click their name.undefined
when rendering /me
lines in moderation cards.component:twitch-chat-input
instances.settings
back to model
, breaking my fix by reverting behavior.Ember.View.views
, so I had to start looking up -view-registry:main
to find things.lables
instead of labels
. /mods
output to not display in chat.ok
instead of True
.


Major bugs
Editing the toolchain may damage the project
In certain conditions, changing the toolchain for a project in the C/C++ Build → Tool Chain Editor page from another plug-in to Eclipse Embedded CDT plug-in might not work; even worse, there are cases when the project is permanently damaged. There is not known way to repair such a broken project; you have to create a new project and copy the content (this is a CDT bug, not a plug-in bug).
Annoying bugs
The Qt plug-ins fail to start with Java 15
Java 15 removed support for JavaScript, and the Qt plug-ins no longer start, throwing a message box:
An internal error occurred during: “Load QML Analyzer”. Cannot invoke “javax.script.ScriptEngine.getContext()” because “this.engine” is null
If you need the Qt plug-ins, the workaround is to downgrade to Java 14.
Otherwise, to get rid of the message box, it is possible to uninstall the Qt plugins:
- go to the Eclipse menu → (Window →) About Eclipse IDE
- click the Installation Details button
- click the Installed Software tab
- select the C/C++ Qt Support feature
- click the Uninstall button
- click Finish
Build fails after rename
Due to a problem buried deep into Eclipse, in certain conditions, immediately after renaming a project, right clicking on a project and choosing Build Configurations → Build All, will display an error window, claiming that the project that the renamed project no longer exist:
The problem is related to a caching mechanism, and is easily cured by exiting Eclipse and opening it again. Another solution is to close only the renamed project and to reopen it.
Add Global Variables… is disabled
In the J-Link or OpenOCD sessions, the Variables view does not allow to add global variables. This is a known CDT DSF bug 219040, not a plug-in bug. As a workaround, you can use watch expressions.
The internal builder fails while generating the listing
Due to a CDT bug, when using the Internal builder it is not possible to generate the additional program listing. If you need it, it is recommended to enable the External builder in the project Properties → C/C++ Build → Builder Settings tab → Builder type.
The Internal builder is long deprecated, it was no longer maintained by the CDT team for many years, and it is strongly recommended not to use it at all.
Conflict while editing tools
Due to a CDT bug, selecting tools in the toolchain editor (the project Properties → C/C++ Build → Tool Chain Editor → Select Tools… button)
complains about a tool conflict:
The message is benign, being triggered by an improper test in CDT (all these extra steps have as input the .elf generated by the linker, and this condition is flagged as error by CDT). You can safely ignore it.
Binaries not visible after build
Due to an Eclipse bug, in certain conditions, after project Build All, the generated binaries, do not show in the Project Explorer. A manual Refresh makes them visible.
References to old project name after renaming
Due to a CDT bug, after renaming a project, the Problems window will complain Invalid project path: Missing project folder or file referring to the old name. The problem can be cured by closing and reopening the project.
Other problems
The Restart button
Due to some bugs in Eclipse, the implementation of his simple button has encountered several problems. Depending on the version you are using, the first time you click this button you might get a message box informing that the button was not enabled. Ignore this message, close the message box and click the button again, this time it’ll be effective.
Tool Settings window update
Not really a bug, but sometimes perceived like an unusual behaviour, enabling/disabling the secondary tools in the C/C++ Build → Settings → Toolchains page and immediately switching to the Tool Settings tab does not show/hide the new tools. It is necessary to press the Apply button for this change to be effective.
Map and listing not removed by Clean
The linker .map
and the assembler .lst
files are not removed when
running the project Clean process. Since these are specific tool
options and not makefile targets, the build process does not know about
them and is not able to remove them when executing the clean target.
Usually these files are generated during each build, so after successful
builds they should always be up to date. If the build does not complete,
it is possible to still have some of these files around, from the previous
build, and this may be confusing. In such cases it is recommended to
manually remove them, or, even better, to completely remove the
Debug/Release build folder and start a clean build.
Advices (to avoid problems)
Toolchain path
DO NOT add the toolchain path to the system path, especially if you are using multiple toolchains (and if you do not do it yet, it is very likely that you will, as soon as new versions of the toolchains will be available). The toolchain path should be configured for each toolchain in the Toolchains tab, in the C/C++ Build → Settings page.
Comments on the content of this page that might be useful for other readers are welcomed here. For question and general support, please use the project forums.


house-hunt
coding
prediction
listing
stats
type
address
Unset
Ideal
Not Ideal
bed
bath
garage
stories
sqft


Virus Spreading Simulation
Population: 125
Vaccinated population: 20%
Vaccine efficacy: 97%
Sick population: 1%
Infection rate: 100%
Social distancing: 0%
Death rate: 3%
This simulation is inspired by this great article.
Other resources with great simulations: article 1, article 2, and tool.
Educational videos about the virus spreading: video 1, video 2, video 3, video 4, video 5, video 6, and video 7.
Stay home during a pandemic, because the social distancing is the most powerful medication.
Note: This simple simulation isn't a 100% real-world simulation, because there are many more factors in the real world and the people aren't just balls that are bouncing.