github.com/hashicorp/packer@v1.14.3/website/content/docs/templates/hcl_templates/syntax-json.mdx (about) 1 --- 2 page_title: JSON syntax reference 3 description: |- 4 A JSON configuration expresses HCL Packer templates as JSON-compatible syntax. Learn about the JSON syntax for creating HCL Packer templates. 5 --- 6 7 # JSON syntax reference 8 9 This topic provides reference information about the JSON syntax you can use to express HCL Packer templates as JSON. For information about the HCL syntax, refer to [HCL syntax reference](/packer/docs/templates/hcl_templates/syntax). 10 11 ## Introduction 12 13 Packer supports templates written in JSON, which is useful when generating portions of a configuration programmatically. This is because you can use existing JSON libraries to prepare the generated 14 configuration files. 15 16 This syntax is not to be confused with the pre-version-1.5 "legacy" Packer 17 templates, which were exclusively JSON and follow a different format. 18 19 The JSON syntax is defined in terms of the native syntax. Everything that can 20 be expressed in native syntax can also be expressed in JSON syntax, but some 21 constructs are more complex to represent in JSON due to limitations of the 22 JSON grammar. 23 24 Packer expects native syntax for files named with a `.pkr.hcl` suffix, and JSON 25 syntax for files named with a `.pkr.json` suffix. If you leave out the `.pkr` 26 portion of suffix, Packer will try to read your json file as a legacy Packer 27 template. 28 29 The low-level JSON syntax, just as with the native syntax, is defined in terms 30 of a specification called _HCL_. It is not necessary to know all of the details 31 of HCL syntax or its JSON mapping in order to use Packer, and so this page 32 summarizes the most important differences between native and JSON syntax. If 33 you are interested, you can find a full definition of HCL's JSON syntax in [its 34 specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md). 35 36 ## JSON File Structure 37 38 At the root of any JSON-based Packer configuration is a JSON object. The 39 properties of this object correspond to the top-level block types of the 40 Packer language. For example: 41 42 ```json 43 { 44 "variables": { 45 "example": "value" 46 } 47 } 48 ``` 49 50 Each top-level object property must match the name of one of the expected 51 top-level block types. Block types that expect labels, such as `variable` shown 52 above, are represented by one nested object value for each level of label. 53 `source` blocks expect two labels, so two levels of nesting are required: 54 55 ```json 56 { 57 "source": { 58 "amazon-ebs": { 59 "example": { 60 "instance_type": "t2.micro", 61 "ami_name": "ami-abc123" 62 } 63 } 64 } 65 } 66 ``` 67 68 After any nested objects representing the labels, finally one more nested 69 object represents the body of the block itself. In the above example the 70 `instance_type` and `ami_name` arguments for `source "amazon-ebs" "example"` 71 are specified. 72 73 Taken together, the above two configuration files are equivalent to the 74 following blocks in the native syntax: 75 76 ```hcl 77 variables { 78 example = "value" 79 } 80 81 source "amazon-ebs" "example" { 82 instance_type = "t2.micro" 83 ami_name = "ami-abc123" 84 } 85 ``` 86 87 Within each top-level block type the rules for mapping to JSON are slightly 88 different (see [block-type-specific exceptions](#block-type-specific-exceptions) below), but the following general rules apply in most cases: 89 90 - The JSON object representing the block body contains properties that 91 correspond either to argument names or to nested block type names. 92 93 - Where a property corresponds to an argument that accepts 94 [arbitrary expressions](/packer/docs/templates/hcl_templates/expressions) in the native syntax, the 95 property value is mapped to an expression as described under 96 [_Expression Mapping_](#expression-mapping) below. For arguments that 97 do _not_ accept arbitrary expressions, the interpretation of the property 98 value depends on the argument, as described in the 99 [block-type-specific exceptions](#block-type-specific-exceptions) 100 given later in this page. 101 102 - Where a property name corresponds to an expected nested block type name, 103 the value is interpreted as described under 104 [_Nested Block Mapping_](#nested-block-mapping) below, unless otherwise 105 stated in [the block-type-specific exceptions](#block-type-specific-exceptions) 106 given later in this page. 107 108 ## Expression Mapping 109 110 Since JSON grammar is not able to represent all of the Packer language 111 [expression syntax](/packer/docs/templates/hcl_templates/expressions), JSON values interpreted as expressions 112 are mapped as follows: 113 114 | JSON | Packer Language Interpretation | 115 | ------- | -------------------------------------------------------------------------------------------------------------------------------- | 116 | Boolean | A literal `bool` value. | 117 | Number | A literal `number` value. | 118 | String | Parsed as a [string template](/packer/docs/templates/hcl_templates/expressions#string-templates) and then evaluated as described below. | 119 | Object | Each property value is mapped per this table, producing an `object(...)` value with suitable attribute types. | 120 | Array | Each element is mapped per this table, producing a `tuple(...)` value with suitable element types. | 121 | Null | A literal `null`. | 122 123 When a JSON string is encountered in a location where arbitrary expressions are 124 expected, its value is first parsed as a [string template](/packer/docs/templates/hcl_templates/expressions#string-templates) 125 and then it is evaluated to produce the final result. 126 127 If the given template consists _only_ of a single interpolation sequence, 128 the result of its expression is taken directly, without first converting it 129 to a string. This allows non-string expressions to be used within the 130 JSON syntax. 131 132 ## Nested Block Mapping 133 134 When a JSON object property is named after a nested block type, the value 135 of this property represents one or more blocks of that type. The value of 136 the property must be either a JSON object or a JSON array. 137 138 The simplest situation is representing only a single block of the given type 139 when that type expects no labels, as with the `tags` nested block used 140 within `source` blocks: 141 142 ```json 143 { 144 "source": { 145 "amazon-ebs": { 146 "example": { 147 "tags": { 148 "key": "value" 149 } 150 } 151 } 152 } 153 } 154 ``` 155 156 The above is equivalent to the following native syntax configuration: 157 158 ```hcl 159 source "amazon-ebs" "example" { 160 tags = { 161 key = "value" 162 } 163 } 164 ``` 165 166 When the nested block type requires one or more labels, or when multiple 167 blocks of the same type can be given, the mapping gets a little more 168 complicated. For example, the `provisioner` nested block type used 169 within `build` blocks expects a label giving the provisioner to use, 170 and the ordering of provisioner blocks is significant to decide the order 171 of operations. 172 173 The following native syntax example shows a `build` block with a number 174 of provisioners of different types: 175 176 ```hcl 177 build { 178 # (source configuration omitted for brevity) 179 180 provisioner "shell-local" { 181 inline = ["echo 'Hello World' >example.txt"] 182 } 183 provisioner "file" { 184 source = "example.txt" 185 destination = "/tmp/example.txt" 186 } 187 provisioner "shell" { 188 inline = [ 189 "sudo install-something -f /tmp/example.txt", 190 ] 191 } 192 } 193 ``` 194 195 In order to preserve the order of these blocks, you must use a JSON array 196 as the direct value of the property representing this block type, as in 197 this JSON equivalent of the above: 198 199 ```json 200 { 201 "build": { 202 "//": "(source configuration omitted for brevity)", 203 204 "provisioner": [ 205 { 206 "shell-local": { 207 "inline": ["echo 'Hello World' >example.txt"] 208 } 209 }, 210 { 211 "file": { 212 "source": "example.txt", 213 "destination": "/tmp/example.txt" 214 } 215 }, 216 { 217 "shell": { 218 "inline": ["sudo install-something -f /tmp/example.txt"] 219 } 220 } 221 ] 222 } 223 } 224 ``` 225 226 Each element of the `provisioner` array is an object with a single property 227 whose name represents the label for each `provisioner` block. For block types 228 that expect multiple labels, this pattern of alternating array and object 229 nesting can be used for each additional level. 230 231 If a nested block type requires labels but the order does _not_ matter, you 232 may omit the array and provide just a single object whose property names 233 correspond to unique block labels. This is allowed as a shorthand for the above 234 for simple cases, but the alternating array and object approach is the most 235 general. We recommend using the most general form if systematically converting 236 from native syntax to JSON, to ensure that the meaning of the configuration is 237 preserved exactly. 238 239 ### Comment Properties 240 241 Although we do not recommend hand-editing of JSON syntax configuration files 242 -- this format is primarily intended for programmatic generation and consumption -- 243 a limited form of _comments_ are allowed inside JSON objects that represent 244 block bodies using a special property name: 245 246 ```json 247 { 248 "source": { 249 "amazon-ebs": { 250 "example": { 251 "//": "This instance runs the scheduled tasks for backup", 252 253 "instance_type": "t2.micro", 254 "ami_name": "ami-abc123" 255 } 256 } 257 } 258 } 259 ``` 260 261 In any object that represents a block body, properties named `"//"` are 262 ignored by Packer entirely. This exception does _not_ apply to objects 263 that are being [interpreted as expressions](#expression-mapping), where this 264 would be interpreted as an object type attribute named `"//"`. 265 266 This special property name can also be used at the root of a JSON-based 267 configuration file. This can be useful to note which program created the file. 268 269 ```json 270 { 271 "//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!" 272 } 273 ``` 274 275 ## Block-type-specific Exceptions 276 277 [inpage-block]: #block-type-specific-exceptions 278 279 Certain arguments within specific block types are processed in a special way, 280 and so their mapping to the JSON syntax does not follow the general rules 281 described above. The following sub-sections describe the special mapping rules 282 that apply to each top-level block type. 283 284 ### `variable` blocks 285 286 All arguments inside `variable` blocks have non-standard mappings to JSON: 287 288 - `type`: a string containing a type expression, like `"string"` or `"list(string)"`. 289 - `default`: a literal JSON value that can be converted to the given type. 290 Strings within this value are taken literally and _not_ interpreted as 291 string templates. 292 - `description`: a literal JSON string, _not_ interpreted as a template. 293 294 ```json 295 { 296 "variable": { 297 "example": { 298 "type": "string", 299 "default": "hello" 300 } 301 } 302 } 303 ```