Subscribe to the Spacelift Blog newsletter, Mission Infrastructure |

Sign Up ➡️

Terraform

Terraform Jsonencode Function – Definition & Examples

Terraform Jsonencode Function

The Terraform jsonencode function converts native HCL values (maps, lists, objects) into a JSON-formatted string. It’s most commonly used when a resource expects a JSON string as input, such as an AWS IAM policy or an Azure Policy definition, letting you define those structures directly in HCL rather than maintaining separate JSON files.

In this article, you’ll learn what jsonencode (and its counterpart jsondecode) do, how to use them, and when to choose them over alternatives like heredoc syntax. We’ll walk through seven practical examples covering IAM policies, template files, for loops, and more.

We will cover:

  1. What is the jsonencode function in Terraform?
  2. What is the jsondecode function in Terraform?
  3. How to use the jsonencode Terraform function?
  4. Terraform jsonencode function use case examples
  5. What is the difference between jsonencode and jsondecode in Terraform?
  6. What is the difference between jsonencode and heredoc in Terraform?

What is the jsonencode function in Terraform?

The jsonencode function in Terraform converts a Terraform value (such as a map, list, or object) into a JSON-formatted string. It’s typically used when a resource or module expects a JSON string input, such as an IAM policy in AWS or a role definition in Azure. 

What is the jsondecode function in Terraform?

The jsondecode function in Terraform converts a JSON-formatted string into a native Terraform value (map, list, string, number, etc.). It is the opposite of the jsonencode function and is typically used to parse external data passed as a JSON string, such as data from a file, remote source, or environment variable. 

Read more about other Terraform functions, expressions, and loops.

How to use the jsonencode Terraform function?

To play around with the jsonencode function, you can use the Terraform console. Simply type terraform console into your terminal to start.

Enter jsonencode({"hello"="world"}) — The output displayed will be in JSON format.

terraform jsonencode examples

Note that the jsonencode cannot directly map to all types available in JSON formatting because there are differences between how the types are represented between HCL (Hashicorp configuration language) and JSON.

Terraform to JSON data types are mapped as follows:

Terraform type JSON equivalent Information lost
string String None
number Number None
bool Boolean None
list(...) Array None
tuple([...]) Array Element types
set(...) Array Ordering and uniqueness not guaranteed
map(...) Object None
object({...}) Object Attribute types
null null None

JSON lacks constructs for distinguishing set from list, or object from map, so type constraints and uniqueness/order guarantees are lost.

Terraform jsonencode function use case examples

For the following examples, we will create a simple JSON file:

yoda.json

{
  "name": "Yoda",
  "age": 900,
  "city": "Dagobah System"
}

Example 1: Using JSON files as input variables and local variables

In this example, we will use the yoda.json file as an input variable, have Terraform use the jsondecode function in the locals, and then finally output the results.

variable "json_input" {
  description = "Path to the JSON input file"
  type        = string
}

locals {
  input_data = jsondecode(file(var.json_input))
}

output "name" {
  value = local.input_data.name
}

output "age" {
  value = local.input_data.age
}

output "city" {
  value = local.input_data.city
}
  1. We define a variable json_input to specify the path to the JSON input file.
  2. We decode the JSON content using the jsondecode function and store it in the local.input_data variable. The file function specifies we need to read the JSON contents from a file.
  3. We define outputs for each key in the JSON, making the data available for other parts of your Terraform code. You can reference it elsewhere in your Terraform code using local.input_data.name, local.input_data.age, and local.input_data.city.

To run the code, in your terminal, specify the variable directly with the -var flag, which points to the path of the yoda.json file:

terraform init
terraform apply -var="json_input=yoda.json"
terraform jsonencode variable

Example 2: Passing in JSON via environment variables

In this example, we will define some JSON as an environment variable and pass it into our Terraform configuration.

To set the environment variables, run the following on the terminal:

export TF_VAR_json_input='{"name": "Yoda", "age": 900, "city": "Dagobah System"}'

Environment variables can be used to set Terraform variables using TF_VAR.

The _json_imput part defines the name of the variable we want to set. This can then be referenced directly in the Terraform code (without the need for the file function this time):

variable "json_input" {
  description = "JSON input"
  type        = string
  default     = ""
}

locals {
  input_data = jsondecode(var.json_input)
}

output "name" {
  value = local.input_data.name
}

output "age" {
  value = local.input_data.age
}

output "city" {
  value = local.input_data.city
}

To see the results, run:

terraform init
terraform apply
jsonencode terraform

Example 3: Decoding JSON strings to Terraform maps

In this example, we will output the values as a Terraform map and pass the JSON in directly on the terminal.

Note that the outputs now have the values for each key contained in [""] .

variable "json_input" {
  description = "JSON input"
  type        = string
  default     = ""
}

locals {
  input_data = jsondecode(var.json_input)
}

output "name" {
  value = local.input_data["name"]
}

output "age" {
  value = local.input_data["age"]
}

output "city" {
  value = local.input_data["city"]
}

To test the output we can run:

terraform init
terraform apply -var='json_input={"name": "Yoda", "age": 900, "city": "Dagobah System"}'
terraform jsonencode list

Example 4: Using jsonencode in the template file

Suppose you have a template file, for example, a configuration file, and you want to include some data as a JSON-encoded string in that file.

Our template file looks like this:

template.tpl

{
  "app_config": ${app_config}
}

Our Terraform configuration looks like this:

example4.tf

# Define a variable with configuration data
variable "app_config" {
  type = map(string)
  default = {
    name = "Yoda"
    age  = "900"
    city = "Dagobah System"
  }
}

# Create a local file using the rendered template
resource "local_file" "app_config" {
  filename = "app_config.json"
  content  = templatefile("template.tpl", {
    app_config = jsonencode(var.app_config)
  })
}

First, you define the data you want to encode as a JSON string — in this case, a map(string) variable holding our configuration values.

Instead of the older data “template_file” block, we now use the built-in templatefile() function directly inside the resource block. It takes two arguments: the path to the template file (template.tpl) and a map of variables to substitute into it. Here, we pass app_config as a JSON-encoded string using jsonencode().

Finally, the local_file resource writes the rendered output to app_config.json on disk.

To run the example:

terraform init
terraform apply

On confirming the apply, a file called app_config.json will be generated in the local directory containing the map contents in JSON format:

{
  "app_config": {"age":"900","city":"Dagobah System","name":"Yoda"}
}

Note: The templatefile() function replaces the older data “template_file” data source, which was deprecated in Terraform 0.12. Prefer templatefile() in all new configurations; it achieves the same result with less boilerplate.

Example 5: Using jsonencode with the for loop

You can use jsonencode in conjunction with a for loop in Terraform to generate JSON data structures dynamically. In this example, we have a list of items, which we will encode into a JSON array using a for loop.

Our template.tpl file looks like this:

{
  "items": ${items_json}
}

example5.tf:

# Define a list of items
variable "items" {
  type    = list(string)
  default = ["Yoda", "Darth Vader", "Salacious Crumb"]
}

# Render the template
data "template_file" "items_template" {
  template = file("template.tpl")
  vars = {
    items_json = jsonencode([for item in var.items : { name = item }])
  }
}

# Create a local file to save the generated JSON
resource "local_file" "items_json" {
  filename = "items.json"
  content  = data.template_file.items_template.rendered
}

This time, inside the vars block, we use a for loop to iterate over each item in the var.items list. In each iteration, we create a map with the key “name” and the value as the current item. This list of maps is then passed to jsonencode to create a JSON array.

terraform init
terraform apply
terraform jsonencode policy

On confirmation of the apply, an items.json file is generated in the local directory containing the following JSON:

{
  "items": [{"name":"Yoda"},{"name":"Darth Vader"},{"name":"Salacious Crumb"}]
}

Example 6: Creating IAM policies using jsonencode function

Creating IAM policies in Terraform using the jsonencode function can be useful when you need to define fine-grained permissions for your AWS resources.

IAM policies are defined as JSON documents, and you can use the jsonencode function to create these policy documents in your Terraform configuration.

# Define a map of IAM policy statements
variable "iam_policy_statements" {
  type = list(object({
    action   = list(string)
    resource = string
  }))
  default = [
    {
      action   = ["s3:GetObject", "s3:ListBucket"]
      resource = "arn:aws:s3:::my-bucket/*"
    },
    {
      action   = ["s3:PutObject"]
      resource = "arn:aws:s3:::my-bucket/upload/*"
    },
    # Add more policy statements as needed
  ]
}

# Encode the IAM policy using jsonencode
locals {
  iam_policy_document = jsonencode({
    Version = "2012-10-17",
    Statement = [
      for statement in var.iam_policy_statements : {
        Action   = statement.action,
        Effect   = "Allow",
        Resource = statement.resource,
      }
    ]
  })
}

# Create an IAM policy
resource "aws_iam_policy" "example" {
  name        = "example-policy"
  description = "Example IAM policy"
  policy      = local.iam_policy_document
}

# Attach the policy to a user, group, or role as needed
  1. The variable iam_policy_statements represents a list of IAM policy statements. Each statement includes an action (a list of allowed actions) and a resource (the AWS resource to which the actions apply).
  2. The jsonencode function in the locals block generates the JSON document for the IAM policy. We use a for loop to iterate over the policy statements defined in the variable and structure them into the required format.
  3. The IAM policy is created using the aws_iam_policy resource. This resource’s policy attribute is set to the JSON-encoded IAM policy document from the locals block.
  4. Finally, you can attach the created policy to an IAM user, group, or role as needed by referencing the aws_iam_policy.example resource in the respective resource block (aws_iam_user_policy_attachment, aws_iam_group_policy_attachment, or aws_iam_role_policy_attachment).

Example 7: Creating Azure Policy definitions with jsonencode function

Azure Policy definitions are typically defined as JSON objects, and you can use jsonencode to create those JSON objects within your Terraform configuration.

The below example shows an Azure policy rule enforcing restrictions if certain tags are applied. You can reference it elsewhere in your code by referring to policy_rule.

# Define an Azure Policy definition
resource "azurerm_policy_definition" "example" {
  name         = "example-policy"
  display_name = "Example Policy"
  description  = "An example Azure Policy definition"
  policy_type  = "Custom"
  mode         = "All"

  metadata {
    category = "General"
  }

  # Encode the policy rule using jsonencode
  policy_rule = jsonencode({
    if {
      allOf = [
        {
          field = "tags['environment']"
          equals = "production"
        },
        {
          field = "tags['costCenter']"
          notLike = "HR-*"
        }
      ]
    }
    then {
      effect = "deny"
    }
  })
}

After defining the policy, you can associate it with a policy assignment to enforce it within a particular scope, such as the subscription level:

resource "azurerm_policy_assignment" "example" {
  name                 = "example-assignment"
  scope                = "/subscriptions/<subscription_id>"
  policy_definition_id = azurerm_policy_definition.example.id
}

What is the difference between jsonencode and jsondecode in Terraform?

jsonencode converts a Terraform expression (like a map or list) into a valid JSON string. It’s commonly used when passing structured data to APIs or templates that expect JSON. jsondecode does the reverse. It parses a JSON string and turns it into a Terraform expression you can use in logic or interpolation.

What is the difference between jsonencode and heredoc in Terraform?

jsonencode is specifically for encoding structured data into a JSON string, making it suitable for creating JSON-based configuration files or policy definitions. Heredoc is a way to include multi-line strings directly in your Terraform configuration.

Heredoc allows you to define a block of text without escaping special characters or worrying about JSON formatting. It is often used to embed text, scripts, or configuration files in your Terraform code.

For reference, Heredoc syntax within a resource block looks like the following:

resource "example_resource" "example" {
  config_script = <<-EOT
    echo "This is a sample script"
  EOT
}

Use jsonencode when precision and structural correctness matter, such as rendering data for APIs or configuration files and heredoc for readable templates or inline file content.

As Sqills grew and transitioned to the cloud, it was no longer practical or desirable to have the infrastructure engineers automate Terraform with Bash scripts. They needed a low-maintenance Terraform automation solution they could depend on — and that’s when they discovered Spacelift.

Spacelift customer case study

Read the full story

How to manage Terraform resources with Spacelift

Terraform is really powerful, but to achieve an end-to-end secure GitOps approach, you need a platform that can run your Terraform workflows. Spacelift is the infrastructure orchestration platform built for the AI-accelerated software era, giving you access to a powerful CI/CD workflow with features such as:

  • OPA-based policies to control approvals, resource creation, parameters, and pull request behavior.
  • Multi-IaC workflows to combine Terraform with Kubernetes, Ansible, OpenTofu, Pulumi, and CloudFormation, with dependencies and shared outputs.
  • Self-service infrastructure with Templates and Blueprints so teams can provision infrastructure through simple forms.
  • Spacelift Intelligence for natural language provisioning, diagnostics, and operational insight across your workflows.
  • Integrations with third-party tools, including security scanners via Custom Inputs.

Spacelift also supports private workers so you can execute workflows inside your own infrastructure.

You can check it out for free by creating a trial account or booking a demo with one of our engineers.

Key points

Using the JSON encode and the opposite jsondecode functions, you can handle JSON files in your Terraform configuration files. Data structures can be manipulated as needed to read in or create new JSON files for common purposes, such as IAM assignments in AWS or creating Azure Policy.

Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Manage Terraform better with Spacelift

Orchestrate Terraform workflows with policy as code, drift detection, resource visualization, context sharing, and programmatic configuration.

Start free trial

Frequently asked questions

  • What does jsonencode do in Terraform?

    jsonencode() converts any valid Terraform value (string, number, list, map, object, etc.) into a compact JSON string. It minifies the output by design, removing all unnecessary whitespace. 

  • How to escape quotes or special characters?

    Escaping is handled automatically. For example, double quotes (") inside strings become \", and newline characters become \n. You don’t need to manually escape special characters unless you’re nesting the resulting JSON inside another string (e.g., a template or shell command), in which case you might need additional escaping layers.

  • Does jsonencode pretty-print?

    No, jsonencode() always emits one-line, minified JSON. This behavior is by design and cannot currently be changed.

    To pretty-print the JSON for readability, you can:

    • Pipe the value through the Terraform console:
      terraform console <<< 'jsonencode(var.example)' | jq
    • Use templatefile() with manual indentation logic (though it’s tedious and error-prone).
  • Is the encoded JSON stored in the state file?

    Yes. If you use jsonencode() inside a local, output, or resource block, its result can be persisted in the Terraform state file.

    As a best practice:

    • Mark outputs containing sensitive data with sensitive = true
    • Use secure state backends (e.g., S3 with encryption, Terraform Cloud, etc.)
    • Avoid placing secrets in values encoded via jsonencode(), if possible
  • Does jsonencode support YAML?

    No. jsonencode() is strictly for JSON. For YAML support, use yamlencode() to convert a Terraform value to YAML and yamldecode() to parse YAML into a Terraform value.

  • Why use jsonencode instead of raw JSON strings in Terraform?

    jsonencode lets Terraform construct JSON from HCL values, so you get automatic escaping, type safety, and the ability to reference variables or expressions inline. Raw JSON strings are opaque to Terraform, meaning typos or malformed syntax won’t surface until apply time. Using jsonencode also keeps your code readable and consistent with the rest of your HCL configuration.

Terraform Functions Cheat Sheet

Grab our ultimate cheat sheet PDF for all
the Terraform functions you need on hand.

Share your data and download the cheat sheet