github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/website/docs/configuration/syntax-json.html.md (about) 1 --- 2 layout: "docs" 3 page_title: "JSON Configuration Syntax - Configuration Language" 4 sidebar_current: "docs-config-syntax-json" 5 description: |- 6 In addition to the native syntax that is most commonly used with Terraform, 7 the Terraform language can also be expressed in a JSON-compatible syntax. 8 --- 9 10 # JSON Configuration Syntax 11 12 -> **Note:** This page is about Terraform 0.12 and later. The JSON configuration 13 syntax in 0.11 and earlier was never formally documented. For other information 14 about Terraform 0.11 and earlier, see 15 [0.11 Configuration Language](../configuration-0-11/index.html). 16 17 Most Terraform configurations are written in 18 [the native Terraform language syntax](./syntax.html), which is designed to be 19 easy for humans to read and update. 20 21 Terraform also supports an alternative syntax that is JSON-compatible. This 22 syntax is useful when generating portions of a configuration programmatically, 23 since existing JSON libraries can be used to prepare the generated 24 configuration files. 25 26 The JSON syntax is defined in terms of the native syntax. Everything that can 27 be expressed in native syntax can also be expressed in JSON syntax, but some 28 constructs are more complex to represent in JSON due to limitations of the 29 JSON grammar. 30 31 Terraform expects native syntax for files named with a `.tf` suffix, and 32 JSON syntax for files named with a `.tf.json` suffix. 33 34 The low-level JSON syntax, just as with the native syntax, is defined in terms 35 of a specification called _HCL_. It is not necessary to know all of the details 36 of HCL syntax or its JSON mapping in order to use Terraform, and so this page 37 summarizes the most important differences between native and JSON syntax. 38 If you are interested, you can find a full definition of HCL's JSON syntax 39 in [its specification](https://github.com/hashicorp/hcl/blob/hcl2/hcl/json/spec.md). 40 41 ## JSON File Structure 42 43 At the root of any JSON-based Terraform configuration is a JSON object. The 44 properties of this object correspond to the top-level block types of the 45 Terraform language. For example: 46 47 ```json 48 { 49 "variable": { 50 "example": { 51 "default": "hello" 52 } 53 } 54 } 55 ``` 56 57 Each top-level object property must match the name of one of the expected 58 top-level block types. Block types that expect labels, such as `variable` 59 shown above, are represented by one nested object value for each level 60 of label. `resource` blocks expect two labels, so two levels of nesting 61 are required: 62 63 ```json 64 { 65 "resource": { 66 "aws_instance": { 67 "example": { 68 "instance_type": "t2.micro", 69 "ami": "ami-abc123" 70 } 71 } 72 } 73 } 74 ``` 75 76 After any nested objects representing the labels, finally one more nested 77 object represents the body of the block itself. In the above examples, the 78 `default` argument for `variable "example"` and the `instance_type` and 79 `ami` arguments for `resource "aws_instance" "example"` are specified. 80 81 Taken together, the above two configuration files are equivalent to the 82 following blocks in the native syntax: 83 84 ```hcl 85 variable "example" { 86 default = "hello" 87 } 88 89 resource "aws_instance" "example" { 90 instance_type = "t2.micro" 91 ami = "ami-abc123" 92 } 93 ``` 94 95 Within each top-level block type the rules for mapping to JSON are slightly 96 different (see the [block-type-specific exceptions](#block-type-specific-exceptions) below), but the following general rules apply in most cases: 97 98 * The JSON object representing the block body contains properties that 99 correspond either to argument names or to nested block type names. 100 101 * Where a property corresponds to an argument that accepts 102 [arbitrary expressions](./expressions.html) in the native syntax, the 103 property value is mapped to an expression as described under 104 [_Expression Mapping_](#expression-mapping) below. For arguments that 105 do _not_ accept arbitrary expressions, the interpretation of the property 106 value depends on the argument, as described in the 107 [block-type-specific exceptions](#block-type-specific-exceptions) 108 given later in this page. 109 110 * Where a property name corresponds to an expected nested block type name, 111 the value is interpreted as described under 112 [_Nested Block Mapping_](#nested-block-mapping) below, unless otherwise 113 stated in [the block-type-specific exceptions](#block-type-specific-exceptions) 114 given later in this page. 115 116 ## Expression Mapping 117 118 Since JSON grammar is not able to represent all of the Terraform language 119 [expression syntax](./expressions.html), JSON values interpreted as expressions 120 are mapped as follows: 121 122 | JSON | Terraform Language Interpretation | 123 | ------- | ------------------------------------------------------------------------------------------------------------- | 124 | Boolean | A literal `bool` value. | 125 | Number | A literal `number` value. | 126 | String | Parsed as a [string template](./expressions.html#string-templates) and then evaluated as described below. | 127 | Object | Each property value is mapped per this table, producing an `object(...)` value with suitable attribute types. | 128 | Array | Each element is mapped per this table, producing a `tuple(...)` value with suitable element types. | 129 | Null | A literal `null`. | 130 131 When a JSON string is encountered in a location where arbitrary expressions are 132 expected, its value is first parsed as a [string template](./expressions.html#string-templates) 133 and then it is evaluated to produce the final result. 134 135 If the given template consists _only_ of a single interpolation sequence, 136 the result of its expression is taken directly, without first converting it 137 to a string. This allows non-string expressions to be used within the 138 JSON syntax: 139 140 ```json 141 { 142 "output": { 143 "example": { 144 "value": "${aws_instance.example}" 145 } 146 } 147 } 148 ``` 149 150 The `output "example"` declared above has the object value representing the 151 given `aws_instance` resource block as its value, rather than a string value. 152 This special behavior does not apply if any literal or control sequences appear 153 in the template; in these other situations, a string value is always produced. 154 155 ## Nested Block Mapping 156 157 When a JSON object property is named after a nested block type, the value 158 of this property represents one or more blocks of that type. The value of 159 the property must be either a JSON object or a JSON array. 160 161 The simplest situation is representing only a single block of the given type 162 when that type expects no labels, as with the `lifecycle` nested block used 163 within `resource` blocks: 164 165 ```json 166 { 167 "resource": { 168 "aws_instance": { 169 "example": { 170 "lifecycle": { 171 "create_before_destroy": true 172 } 173 } 174 } 175 } 176 } 177 ``` 178 179 The above is equivalent to the following native syntax configuration: 180 181 ```hcl 182 resource "aws_instance" "example" { 183 lifecycle { 184 create_before_destroy = true 185 } 186 } 187 ``` 188 189 When the nested block type requires one or more labels, or when multiple 190 blocks of the same type can be given, the mapping gets a little more 191 complicated. For example, the `provisioner` nested block type used 192 within `resource` blocks expects a label giving the provisioner to use, 193 and the ordering of provisioner blocks is significant to decide the order 194 of operations. 195 196 The following native syntax example shows a `resource` block with a number 197 of provisioners of different types: 198 199 ```hcl 200 resource "aws_instance" "example" { 201 # (resource configuration omitted for brevity) 202 203 provisioner "local-exec" { 204 command = "echo 'Hello World' >example.txt" 205 } 206 provisioner "file" { 207 source = "example.txt" 208 destination = "/tmp/example.txt" 209 } 210 provisioner "remote-exec" { 211 inline = [ 212 "sudo install-something -f /tmp/example.txt", 213 ] 214 } 215 } 216 ``` 217 218 In order to preserve the order of these blocks, you must use a JSON array 219 as the direct value of the property representing this block type, as in 220 this JSON equivalent of the above: 221 222 ```json 223 { 224 "resource": { 225 "aws_instance": { 226 "example": { 227 "provisioner": [ 228 { 229 "local-exec": { 230 "command": "echo 'Hello World' >example.txt" 231 } 232 }, 233 { 234 "file": { 235 "source": "example.txt", 236 "destination": "/tmp/example.txt" 237 } 238 }, 239 { 240 "remote-exec": { 241 "inline": ["sudo install-something -f /tmp/example.txt"] 242 } 243 } 244 ] 245 } 246 } 247 } 248 } 249 ``` 250 251 Each element of the `provisioner` array is an object with a single property 252 whose name represents the label for each `provisioner` block. For block types 253 that expect multiple labels, this pattern of alternating array and object 254 nesting can be used for each additional level. 255 256 If a nested block type requires labels but the order does _not_ matter, you 257 may omit the array and provide just a single object whose property names 258 correspond to unique block labels. This is allowed as a shorthand for the above 259 for simple cases, but the alternating array and object approach is the most 260 general. We recommend using the most general form if systematically converting 261 from native syntax to JSON, to ensure that the meaning of the configuration is 262 preserved exactly. 263 264 ### Comment Properties 265 266 Although we do not recommend hand-editing of JSON syntax configuration files 267 -- this format is primarily intended for programmatic generation and consumption -- 268 a limited form of _comments_ are allowed inside JSON objects that represent 269 block bodies using a special property name: 270 271 ```json 272 { 273 "resource": { 274 "aws_instance": { 275 "example": { 276 "//": "This instance runs the scheduled tasks for backup", 277 278 "instance_type": "t2.micro", 279 "ami": "ami-abc123" 280 } 281 } 282 } 283 } 284 ``` 285 286 In any object that represents a block body, properties named `"//"` are 287 ignored by Terraform entirely. This exception does _not_ apply to objects 288 that are being [interpreted as expressions](#expression-mapping), where this 289 would be interpreted as an object type attribute named `"//"`. 290 291 This special property name can also be used at the root of a JSON-based 292 configuration file. This can be useful to note which program created the file. 293 294 ```json 295 { 296 "//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!", 297 298 "output": { 299 "example": { 300 "value": "${aws_instance.example}" 301 } 302 } 303 } 304 ``` 305 306 ## Block-type-specific Exceptions 307 308 [inpage-block]: #block-type-specific-exceptions 309 310 Certain arguments within specific block types are processed in a special way 311 by Terraform, and so their mapping to the JSON syntax does not follow the 312 general rules described above. The following sub-sections describe the special 313 mapping rules that apply to each top-level block type. 314 315 ### `resource` and `data` blocks 316 317 Some meta-arguments for the `resource` and `data` block types take direct 318 references to objects, or literal keywords. When represented in JSON, the 319 reference or keyword is given as a JSON string with no additional surrounding 320 spaces or symbols. 321 322 For example, the `provider` meta-argument takes a `<PROVIDER>.<ALIAS>` reference 323 to a provider configuration, which appears unquoted in the native syntax but 324 must be presented as a string in the JSON syntax: 325 326 ```json 327 { 328 "resource": { 329 "aws_instance": { 330 "example": { 331 "provider": "aws.foo" 332 } 333 } 334 } 335 } 336 ``` 337 338 This special processing applies to the following meta-arguments: 339 340 * `provider`: a single string, as shown above 341 * `depends_on`: an array of strings containing references to named entities, 342 like `["aws_instance.example"]`. 343 * `ignore_changes` within the `lifecycle` block: if set to `all`, a single 344 string `"all"` must be given. Otherwise, an array of JSON strings containing 345 property references must be used, like `["ami"]`. 346 347 Special processing also applies to the `type` argument of any `connection` 348 blocks, whether directly inside the `resource` block or nested inside 349 `provisioner` blocks: the given string is interpreted literally, and not 350 parsed and evaluated as a string template. 351 352 ### `variable` blocks 353 354 All arguments inside `variable` blocks have non-standard mappings to JSON: 355 356 * `type`: a string containing a type expression, like `"string"` or `"list(string)"`. 357 * `default`: a literal JSON value that can be converted to the given type. 358 Strings within this value are taken literally and _not_ interpreted as 359 string templates. 360 * `description`: a literal JSON string, _not_ interpreted as a template. 361 362 ```json 363 { 364 "variable": { 365 "example": { 366 "type": "string", 367 "default": "hello" 368 } 369 } 370 } 371 ``` 372 373 ### `output` blocks 374 375 The `description` and `sensitive` arguments are interpreted as literal JSON 376 values. The `description` string is not interpreted as a string template. 377 378 The `value` argument is [interpreted as an expression](#expression-mapping). 379 380 ```json 381 { 382 "output": { 383 "example": { 384 "value": "${aws_instance.example}" 385 } 386 } 387 } 388 ``` 389 390 ### `locals` blocks 391 392 The value of the JSON object property representing the locals block type 393 must be a JSON object whose property names are the local value names to 394 declare: 395 396 ```json 397 { 398 "locals": { 399 "greeting": "Hello, ${var.name}" 400 } 401 } 402 ``` 403 404 The value of each of these nested properties is 405 [interpreted as an expression](#expression-mapping). 406 407 ### `module` blocks 408 409 The `source` and `version` meta-arguments must be given as literal strings. The 410 values are not interpreted as string templates. 411 412 The `providers` meta-argument must be given as a JSON object whose properties 413 are the compact provider addresses to expose into the child module and whose 414 values are the provider addresses to use from the current module, both 415 given as literal strings: 416 417 ```json 418 { 419 "module": { 420 "example": { 421 "source": "hashicorp/consul/azurerm", 422 "version": "= 1.0.0", 423 "providers": { 424 "aws": "aws.usw1" 425 } 426 } 427 } 428 } 429 ``` 430 431 ### `provider` blocks 432 433 The `alias` and `version` meta-arguments must be given as literal strings. The 434 values are not interpreted as string templates. 435 436 ```json 437 { 438 "provider": { 439 "aws": { 440 "alias": "usw1", 441 "region": "us-west-1" 442 } 443 } 444 } 445 ``` 446 447 ### `terraform` blocks 448 449 Since no settings within `terraform` blocks accept named object references or 450 function calls, all setting values are taken literally. String values are not 451 interpreted as string templates. 452 453 Since only one `backend` block is allowed per `terraform` block, the compact 454 block mapping can be used to represent it, with a nested object containing 455 a single property whose name represents the backend type. 456 457 ```json 458 { 459 "terraform": { 460 "required_version": ">= 0.12.0", 461 "backend": { 462 "s3": { 463 "region": "us-west-2", 464 "bucket": "acme-terraform-states" 465 } 466 } 467 } 468 } 469 ```