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  ```