github.com/hugorut/terraform@v1.1.3/website/docs/language/syntax/json.mdx (about)

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