From a05726630e7913138346bcf30a37f37fa3b7ccba Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 20 Jun 2017 08:07:10 -0700 Subject: [PATCH] json: beginnings of a JSON syntax specification document --- zcl/json/spec.md | 265 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 zcl/json/spec.md diff --git a/zcl/json/spec.md b/zcl/json/spec.md new file mode 100644 index 0000000..b9d7e52 --- /dev/null +++ b/zcl/json/spec.md @@ -0,0 +1,265 @@ +# zcl JSON Syntax Specification + +This is the specification for the JSON serialization for zcl. zcl is a system +for defining configuration languages for applications. The zcl information +model is designed to support multiple concrete syntaxes for configuration, +and this JSON-based format complements [the native syntax](../zclsyntax/spec.md) +by being easy to machine-generate, whereas the native syntax is oriented +towards human authoring and maintenence. + +This syntax is defined in terms of JSON as defined in +[RFC7159](https://tools.ietf.org/html/rfc7159). As such it inherits the JSON +grammar as-is, and merely defines a specific methodology for interpreting +JSON constructs into zcl structural elements and expressions. + +This mapping is defined such that valid JSON-serialized zcl input can be +produced using standard JSON implementations in various programming languages. +_Parsing_ such JSON has some additional constraints not beyond what is normally +supported by JSON parsers, though adaptations are defined to allow processing +with an off-the-shelf JSON parser with certain caveats, described in later +sections. + +## Structural Elements + +The zcl language-agnostic information model defines a _body_ as an abstract +container for attribute definitions and child blocks. A body is represented +in JSON as a JSON _object_. + +As defined in the language-agnostic model, body processing is done in terms +of a schema which provides context for interpreting the body's content. For +JSON bodies, the schema is crucial to allow differentiation of attribute +definitions and block definitions, both of which are represented via object +properties. + +The special property name `"//"`, when used in an object representing a zcl +body, is parsed and ignored. A property with this name can be used to +include human-readable comments. (This special property name is _not_ +processed in this way for any _other_ zcl constructs that are represented as +JSON objects.) + +### Attributes + +Where the given schema describes an attribute with a given name, the object +property with the matching name — if present — serves as the attribute's +definition. + +When a body is being processed in the _dynamic attributes_ mode, each object +property serves as an attribute definition for the attribute whose name +matches the property name. + +The value of an attribute definition property is interpreted as an _expression_, +as described in a later section. + +Given a schema that calls for an attribute named "foo", a JSON object like +the following provides a definition for that attribute: + +```json +{ + "foo": "bar baz" +} +``` + +### Blocks + +Where the given schema describes a block with a given type name, the object +property with the matching name — if present — serves as a definition of +zero or more blocks of that type. + +Processing of child blocks is in terms of nested JSON objects and arrays. +If the schema defines one or more _labels_ for the block type, a nested +object is required for each labelling level, with the object keys serving as +the label values at that level. + +After any labelling levels, the next nested value is either a JSON object +representing a single block body, or a JSON array of JSON objects that each +represent a single block body. Use of an array accommodates the definition +of multiple blocks that have identical type and labels. + +Given a schema that calls for a block type named "foo" with no labels, the +following JSON objects are all valid definitions of zero or more blocks of this +type: + +```json +{ + "foo": { + "child_attr": "baz" + } +} +``` + +```json +{ + "foo": [ + { + "child_attr": "baz" + }, + { + "child_attr": "boz" + } + ] +} +``` +```json +{ + "foo": [] +} +``` + +The first of these defines a single child block of type "foo". The second +defines _two_ such blocks. The final example shows a degenerate definition +of zero blocks, though generators should prefer to omit the property entirely +in this scenario. + +Given a schema that calls for a block type named "foo" with _two_ labels, the +extra label levels must be represented as objects as in the following examples: + +```json +{ + "foo": { + "bar": { + "baz": { + "child_attr": "baz" + }, + "boz": { + "child_attr": "baz" + } + }, + "boz": { + "baz": { + "child_attr": "baz" + }, + } + } +} +``` +```json +{ + "foo": { + "bar": { + "baz": { + "child_attr": "baz" + }, + "boz": { + "child_attr": "baz" + } + }, + "boz": { + "baz": [ + { + "child_attr": "baz" + }, + { + "child_attr": "boz" + } + ] + } + } +} +``` + +Where multiple definitions are included for the same type and labels, the +JSON array is always the value of the property representing the final label, +and contains objects representing block bodies. It is not valid to use an array +at any other point in the block definition structure. + +## Expressions + +JSON lacks a native expression syntax, so the zcl JSON syntax instead defines +a mapping for each of the JSON value types, including a special mapping for +strings that allows optional use of arbitrary expressions. + +### Objects + +When interpreted as an expression, a JSON object represents a value of a zcl +object type. + +Each property of the JSON object represents an attribute of the zcl object type. +The object type is constructed by enumerating the JSON object properties, +creating for each an attribute whose name exactly matches the property name, +and whose type is the result of recursively applying the expression mapping +rules. + +An instance of the constructed object type is then created, whose values +are interpreted by again recursively applying the mapping rules defined in +this section. + +It is an error to define the same property name multiple times within a single +JSON object interpreted as an expression. + +### Arrays + +When interpreted as an expression, a JSON array represents a value of a zcl +tuple type. + +Each element of the JSON array represents an element of the zcl tuple type. +The tuple type is constructed by enumerationg the JSON array elements, creating +for each an element whose type is the result of recursively applying the +expression mapping rules. Correspondance is preserved between the array element +indices and the tuple element indices. + +An instance of the constructed tuple type is then created, whose values are +interpreted by again recursively applying the mapping rules defined in this +section. + +### Numbers + +When interpreted as an expression, a JSON number represents a zcl number value. + +zcl numbers are arbitrary-precision decimal values, so an ideal implementation +of this specification will translate exactly the value given to a number of +corresponding precision. + +In practice, off-the-shelf JSON parsers often do not support customizing the +processing of numbers, and instead force processing as 32-bit or 64-bit +floating point values with a potential loss of precision. It is permissable +for a zcl JSON parser to pass on such limitations _if and only if_ the +available precision and other constraints are defined in its documentation. +Calling applications each have differing precision requirements, so calling +applications are free to select an implementation with more limited precision +capabilities should high precision not be required for that application. + +### Boolean Values + +The JSON boolean values `true` and `false`, when interpreted as expressions, +represent the corresponding zcl boolean values. + +### The Null Value + +The JSON value `null`, when interpreted as an expression, represents a +zcl null value of the dynamic pseudo-type. + +### Strings + +When intepreted as an expression, a JSON string may be interpreted in one of +two ways depending on the evaluation mode. + +If evaluating in literal-only mode (as defined by the syntax-agnostic +information model) the literal string is intepreted directly as a zcl string +value, by directly using the exact sequence of unicode characters represented. +Template interpolations and directives MUST NOT be processed in this mode, +allowing any characters that appear as introduction sequences to pass through +literally: + +```json +"Hello world! Template sequences like ${ are not intepreted here." +``` + +When evaluating in full expression mode (again, as defined by the syntax- +agnostic information model) the literal string is instead interpreted as a +_standalone template_ in the zcl Native Syntax. The expression evaluation +result is then the direct result of evaluating that template with the current +variable scope and function table. + +```json +"Hello, ${name}! Template sequences are interpreted in full expression mode." +``` + +In particular the _Template Interpolation Unwrapping_ requirement from the +zcl native syntax specification must be implemented, allowing the use of +single-interpolation templates to represent expressions that would not +otherwise be representable in JSON, such as the following example where +the result must be a number, rather than a string representation of a number: + +```json +"${ a + b }" +```