website: Note about using jsonencode/yamlencode in templatefile

It's a common source of errors to try to produce JSON or YAML syntax
using string concatenation via our template language but to miss some
details like correct string escaping, quoting, required commas, etc.

The jsonencode and yamlencode functions are a better way to generate JSON
and YAML, but it's not immediately obvious that both of these functions
are available for use in external templates (via templatefile) too.

Given that questions related to this come up a lot in our community forum
and elsewhere, it seems worth having a documentation section to show the
pattern of having a template that consists only of a single function call.
This commit is contained in:
Martin Atkins 2019-12-10 14:40:12 -08:00
parent 28880aa47d
commit bfbd00a23c

View File

@ -64,6 +64,59 @@ backend 10.0.0.2:8080
```
### Generating JSON or YAML from a template
If the string you want to generate will be in JSON or YAML syntax, it's
often tricky and tedious to write a template that will generate valid JSON or
YAML that will be interpreted correctly when using lots of individual
interpolation sequences and directives.
Instead, you can write a template that consists only of a single interpolated
call to either [`jsonencode`](./jsonencode.html) or
[`yamlencode`](./yamlencode.html), specifying the value to encode using
[normal Terraform expression syntax](/docs/configuration/expressions.html)
as in the following examples:
```
${jsonencode({
"backends": [for addr in ip_addrs : "${addr}:${port}"],
})}
```
```
${yamlencode({
"backends": [for addr in ip_addrs : "${addr}:${port}"],
})}
```
Given the same input as the `backends.tmpl` example in the previous section,
this will produce a valid JSON or YAML representation of the given data
structure, without the need to manually handle escaping or delimiters.
In the latest examples above, the repetition based on elements of `ip_addrs` is
achieved by using a
[`for` expression](/docs/configuration/expressions.html#for-expressions)
rather than by using
[template directives](/docs/configuration/expressions.html#directives).
```json
{"backends":["10.0.0.1:8080","10.0.0.2:8080"]}
```
If the resulting template is small, you can choose instead to write
`jsonencode` or `yamlencode` calls inline in your main configuration files, and
avoid creating separate template files at all:
```hcl
locals {
backend_config_json = jsonencode({
"backends": [for addr in ip_addrs : "${addr}:${port}"],
})
}
```
For more information, see the main documentation for
[`jsonencode`](./jsonencode.html) and [`yamlencode`](./yamlencode.html).
## Related Functions
* [`file`](./file.html) reads a file from disk and returns its literal contents