github.com/hashicorp/hcl/v2@v2.20.0/json/spec.md (about) 1 # HCL JSON Syntax Specification 2 3 This is the specification for the JSON serialization for hcl. HCL is a system 4 for defining configuration languages for applications. The HCL information 5 model is designed to support multiple concrete syntaxes for configuration, 6 and this JSON-based format complements [the native syntax](../hclsyntax/spec.md) 7 by being easy to machine-generate, whereas the native syntax is oriented 8 towards human authoring and maintenance 9 10 This syntax is defined in terms of JSON as defined in 11 [RFC7159](https://tools.ietf.org/html/rfc7159). As such it inherits the JSON 12 grammar as-is, and merely defines a specific methodology for interpreting 13 JSON constructs into HCL structural elements and expressions. 14 15 This mapping is defined such that valid JSON-serialized HCL input can be 16 _produced_ using standard JSON implementations in various programming languages. 17 _Parsing_ such JSON has some additional constraints not beyond what is normally 18 supported by JSON parsers, so a specialized parser may be required that 19 is able to: 20 21 - Preserve the relative ordering of properties defined in an object. 22 - Preserve multiple definitions of the same property name. 23 - Preserve numeric values to the precision required by the number type 24 in [the HCL syntax-agnostic information model](../spec.md). 25 - Retain source location information for parsed tokens/constructs in order 26 to produce good error messages. 27 28 ## Structural Elements 29 30 [The HCL syntax-agnostic information model](../spec.md) defines a _body_ as an 31 abstract container for attribute definitions and child blocks. A body is 32 represented in JSON as either a single JSON object or a JSON array of objects. 33 34 Body processing is in terms of JSON object properties, visited in the order 35 they appear in the input. Where a body is represented by a single JSON object, 36 the properties of that object are visited in order. Where a body is 37 represented by a JSON array, each of its elements are visited in order and 38 each element has its properties visited in order. If any element of the array 39 is not a JSON object then the input is erroneous. 40 41 When a body is being processed in the _dynamic attributes_ mode, the allowance 42 of a JSON array in the previous paragraph does not apply and instead a single 43 JSON object is always required. 44 45 As defined in the language-agnostic model, body processing is in terms 46 of a schema which provides context for interpreting the body's content. For 47 JSON bodies, the schema is crucial to allow differentiation of attribute 48 definitions and block definitions, both of which are represented via object 49 properties. 50 51 The special property name `"//"`, when used in an object representing a HCL 52 body, is parsed and ignored. A property with this name can be used to 53 include human-readable comments. (This special property name is _not_ 54 processed in this way for any _other_ HCL constructs that are represented as 55 JSON objects.) 56 57 ### Attributes 58 59 Where the given schema describes an attribute with a given name, the object 60 property with the matching name — if present — serves as the attribute's 61 definition. 62 63 When a body is being processed in the _dynamic attributes_ mode, each object 64 property serves as an attribute definition for the attribute whose name 65 matches the property name. 66 67 The value of an attribute definition property is interpreted as an _expression_, 68 as described in a later section. 69 70 Given a schema that calls for an attribute named "foo", a JSON object like 71 the following provides a definition for that attribute: 72 73 ```json 74 { 75 "foo": "bar baz" 76 } 77 ``` 78 79 ### Blocks 80 81 Where the given schema describes a block with a given type name, each object 82 property with the matching name serves as a definition of zero or more blocks 83 of that type. 84 85 Processing of child blocks is in terms of nested JSON objects and arrays. 86 If the schema defines one or more _labels_ for the block type, a nested JSON 87 object or JSON array of objects is required for each labelling level. These 88 are flattened to a single ordered sequence of object properties using the 89 same algorithm as for body content as defined above. Each object property 90 serves as a label value at the corresponding level. 91 92 After any labelling levels, the next nested value is either a JSON object 93 representing a single block body, or a JSON array of JSON objects that each 94 represent a single block body. Use of an array accommodates the definition 95 of multiple blocks that have identical type and labels. 96 97 Given a schema that calls for a block type named "foo" with no labels, the 98 following JSON objects are all valid definitions of zero or more blocks of this 99 type: 100 101 ```json 102 { 103 "foo": { 104 "child_attr": "baz" 105 } 106 } 107 ``` 108 109 ```json 110 { 111 "foo": [ 112 { 113 "child_attr": "baz" 114 }, 115 { 116 "child_attr": "boz" 117 } 118 ] 119 } 120 ``` 121 122 ```json 123 { 124 "foo": [] 125 } 126 ``` 127 128 The first of these defines a single child block of type "foo". The second 129 defines _two_ such blocks. The final example shows a degenerate definition 130 of zero blocks, though generators should prefer to omit the property entirely 131 in this scenario. 132 133 Given a schema that calls for a block type named "foo" with _two_ labels, the 134 extra label levels must be represented as objects or arrays of objects as in 135 the following examples: 136 137 ```json 138 { 139 "foo": { 140 "bar": { 141 "baz": { 142 "child_attr": "baz" 143 }, 144 "boz": { 145 "child_attr": "baz" 146 } 147 }, 148 "boz": { 149 "baz": { 150 "child_attr": "baz" 151 } 152 } 153 } 154 } 155 ``` 156 157 ```json 158 { 159 "foo": { 160 "bar": { 161 "baz": { 162 "child_attr": "baz" 163 }, 164 "boz": { 165 "child_attr": "baz" 166 } 167 }, 168 "boz": { 169 "baz": [ 170 { 171 "child_attr": "baz" 172 }, 173 { 174 "child_attr": "boz" 175 } 176 ] 177 } 178 } 179 } 180 ``` 181 182 ```json 183 { 184 "foo": [ 185 { 186 "bar": { 187 "baz": { 188 "child_attr": "baz" 189 }, 190 "boz": { 191 "child_attr": "baz" 192 } 193 } 194 }, 195 { 196 "bar": { 197 "baz": [ 198 { 199 "child_attr": "baz" 200 }, 201 { 202 "child_attr": "boz" 203 } 204 ] 205 } 206 } 207 ] 208 } 209 ``` 210 211 ```json 212 { 213 "foo": { 214 "bar": { 215 "baz": { 216 "child_attr": "baz" 217 }, 218 "boz": { 219 "child_attr": "baz" 220 } 221 }, 222 "bar": { 223 "baz": [ 224 { 225 "child_attr": "baz" 226 }, 227 { 228 "child_attr": "boz" 229 } 230 ] 231 } 232 } 233 } 234 ``` 235 236 Arrays can be introduced at either the label definition or block body 237 definition levels to define multiple definitions of the same block type 238 or labels while preserving order. 239 240 A JSON HCL parser _must_ support duplicate definitions of the same property 241 name within a single object, preserving all of them and the relative ordering 242 between them. The array-based forms are also required so that JSON HCL 243 configurations can be produced with JSON producing libraries that are not 244 able to preserve property definition order and multiple definitions of 245 the same property. 246 247 ## Expressions 248 249 JSON lacks a native expression syntax, so the HCL JSON syntax instead defines 250 a mapping for each of the JSON value types, including a special mapping for 251 strings that allows optional use of arbitrary expressions. 252 253 ### Objects 254 255 When interpreted as an expression, a JSON object represents a value of a HCL 256 object type. 257 258 Each property of the JSON object represents an attribute of the HCL object type. 259 The property name string given in the JSON input is interpreted as a string 260 expression as described below, and its result is converted to string as defined 261 by the syntax-agnostic information model. If such a conversion is not possible, 262 an error is produced and evaluation fails. 263 264 An instance of the constructed object type is then created, whose values 265 are interpreted by again recursively applying the mapping rules defined in 266 this section to each of the property values. 267 268 If any evaluated property name strings produce null values, an error is 269 produced and evaluation fails. If any produce _unknown_ values, the _entire 270 object's_ result is an unknown value of the dynamic pseudo-type, signalling 271 that the type of the object cannot be determined. 272 273 It is an error to define the same property name multiple times within a single 274 JSON object interpreted as an expression. In full expression mode, this 275 constraint applies to the name expression results after conversion to string, 276 rather than the raw string that may contain interpolation expressions. 277 278 ### Arrays 279 280 When interpreted as an expression, a JSON array represents a value of a HCL 281 tuple type. 282 283 Each element of the JSON array represents an element of the HCL tuple type. 284 The tuple type is constructed by enumerating the JSON array elements, creating 285 for each an element whose type is the result of recursively applying the 286 expression mapping rules. Correspondence is preserved between the array element 287 indices and the tuple element indices. 288 289 An instance of the constructed tuple type is then created, whose values are 290 interpreted by again recursively applying the mapping rules defined in this 291 section. 292 293 ### Numbers 294 295 When interpreted as an expression, a JSON number represents a HCL number value. 296 297 HCL numbers are arbitrary-precision decimal values, so a JSON HCL parser must 298 be able to translate exactly the value given to a number of corresponding 299 precision, within the constraints set by the HCL syntax-agnostic information 300 model. 301 302 In practice, off-the-shelf JSON serializers often do not support customizing the 303 processing of numbers, and instead force processing as 32-bit or 64-bit 304 floating point values. 305 306 A _producer_ of JSON HCL that uses such a serializer can provide numeric values 307 as JSON strings where they have precision too great for representation in the 308 serializer's chosen numeric type in situations where the result will be 309 converted to number (using the standard conversion rules) by a calling 310 application. 311 312 Alternatively, for expressions that are evaluated in full expression mode an 313 embedded template interpolation can be used to faithfully represent a number, 314 such as `"${1e150}"`, which will then be evaluated by the underlying HCL native 315 syntax expression evaluator. 316 317 ### Boolean Values 318 319 The JSON boolean values `true` and `false`, when interpreted as expressions, 320 represent the corresponding HCL boolean values. 321 322 ### The Null Value 323 324 The JSON value `null`, when interpreted as an expression, represents a 325 HCL null value of the dynamic pseudo-type. 326 327 ### Strings 328 329 When interpreted as an expression, a JSON string may be interpreted in one of 330 two ways depending on the evaluation mode. 331 332 If evaluating in literal-only mode (as defined by the syntax-agnostic 333 information model) the literal string is intepreted directly as a HCL string 334 value, by directly using the exact sequence of unicode characters represented. 335 Template interpolations and directives MUST NOT be processed in this mode, 336 allowing any characters that appear as introduction sequences to pass through 337 literally: 338 339 ```json 340 "Hello world! Template sequences like ${ are not intepreted here." 341 ``` 342 343 When evaluating in full expression mode (again, as defined by the syntax- 344 agnostic information model) the literal string is instead interpreted as a 345 _standalone template_ in the HCL Native Syntax. The expression evaluation 346 result is then the direct result of evaluating that template with the current 347 variable scope and function table. 348 349 ```json 350 "Hello, ${name}! Template sequences are interpreted in full expression mode." 351 ``` 352 353 In particular the _Template Interpolation Unwrapping_ requirement from the 354 HCL native syntax specification must be implemented, allowing the use of 355 single-interpolation templates to represent expressions that would not 356 otherwise be representable in JSON, such as the following example where 357 the result must be a number, rather than a string representation of a number: 358 359 ```json 360 "${ a + b }" 361 ``` 362 363 ## Static Analysis 364 365 The HCL static analysis operations are implemented for JSON values that 366 represent expressions, as described in the following sections. 367 368 Due to the limited expressive power of the JSON syntax alone, use of these 369 static analyses functions rather than normal expression evaluation is used 370 as additional context for how a JSON value is to be interpreted, which means 371 that static analyses can result in a different interpretation of a given 372 expression than normal evaluation. 373 374 ### Static List 375 376 An expression interpreted as a static list must be a JSON array. Each of the 377 values in the array is interpreted as an expression and returned. 378 379 ### Static Map 380 381 An expression interpreted as a static map must be a JSON object. Each of the 382 key/value pairs in the object is presented as a pair of expressions. Since 383 object property names are always strings, evaluating the key expression with 384 a non-`nil` evaluation context will evaluate any template sequences given 385 in the property name. 386 387 ### Static Call 388 389 An expression interpreted as a static call must be a string. The content of 390 the string is interpreted as a native syntax expression (not a _template_, 391 unlike normal evaluation) and then the static call analysis is delegated to 392 that expression. 393 394 If the original expression is not a string or its contents cannot be parsed 395 as a native syntax expression then static call analysis is not supported. 396 397 ### Static Traversal 398 399 An expression interpreted as a static traversal must be a string. The content 400 of the string is interpreted as a native syntax expression (not a _template_, 401 unlike normal evaluation) and then static traversal analysis is delegated 402 to that expression. 403 404 If the original expression is not a string or its contents cannot be parsed 405 as a native syntax expression then static call analysis is not supported.