Terraform HCL to JSON Converter

Convert Terraform HCL to the equivalent .tf.json syntax. Terraform reads both, and the conversion is lossy in one specific way that the output names rather than hides.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Convert. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

An expression becomes a string

JSON has no expression type, so a bare reference has to be wrapped and is then indistinguishable from literal text

resource "aws_s3_bucket" "logs" {
  bucket = var.bucket_name
}

A literal-only block

With no expressions the conversion is lossless, which is the case JSON syntax is good for

resource "aws_s3_bucket" "logs" {
  bucket = "my-logs"
  versioning = true
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Converting a hand-written module to JSON to make it machine-editable

    Every expression becomes a string, so the file gets harder to read and no easier to edit correctly. The information about which strings are expressions is gone.

    Instead:Keep HCL for anything a human maintains. Use JSON syntax only for files a program generates from scratch.

  2. Naming the output .tf

    Terraform picks the parser from the extension, so JSON in a .tf file is a syntax error rather than an alternative syntax.

    Instead:Name it .tf.json.

  3. Assuming a round trip is safe

    HCL to JSON and back cannot recover which strings were expressions, so a bare reference and a literal string containing the same text collapse into one representation.

    Instead:Treat the conversion as one-way. Keep the HCL as the source of truth.

The two syntaxes are equivalent, and the conversion is not lossless

Terraform parses HCL and JSON into the same structure. Going from HCL to JSON loses information that cannot be recovered coming back.

JSON has no expression type

Every value in JSON is a string, a number, a boolean, a list or an object. An HCL expression like var.name is none of those, so in JSON syntax it has to be written as a string and Terraform evaluates any string for interpolation. That means "${var.name}" and a literal string containing that text are indistinguishable in the document, and a round trip back to HCL cannot tell you which was meant.

The file extension picks the parser

JSON syntax goes in a file ending .tf.json, not .tf. Terraform decides which parser to use from the extension alone, so JSON in a .tf file is a syntax error and HCL in a .tf.json file is one too. Both may be used in the same module.

Heredocs do not survive readably

A heredoc is HCL syntax. The same value in JSON is one string with escaped newlines, which is correct and unreadable. An indented heredoc using the dash or tilde form also had its indentation stripped during parsing, and that stripping is not reversible, so a policy document or a user_data script is worth checking by hand after conversion.

Repeated blocks become arrays

Two resource blocks of the same type and name are an error, but two provider blocks or two ingress blocks are not. In JSON those become an array under the same key, which is the correct representation and looks nothing like the HCL that produced it.

When JSON syntax is the right choice

For files a program writes. A generator emitting JSON does not have to get HCL quoting right, and the result is machine-parseable without an HCL library. For files a human maintains, HCL is better in every respect, which is why the expression caveat above matters more than it sounds.

What this cannot see

Whether the converted configuration behaves identically, because that depends on how Terraform evaluates the expressions it now sees as strings. It converts the structure, in your browser, and runs nothing. Validate the output with terraform validate before relying on it.

More terraform tools

Terraform Validator & Formatter Does it parse, and is it formatted? Terraform dynamic Block Generator It is ingress.value, not each.value Terraform check and precondition Generator A failed check does not stop the apply Terraform variables.tf Generator From the var. references you already wrote Terraform Unused Declaration Linter Dead variables, locals and data sources Terraform Atlantis YAML Generator when_modified misses your modules Terraform Function Tester and HCL Console terraform console, in a tab Terraform for Expression Tester Where do the keys collide? Terraform Interpolation Tester null becomes an empty string Terraform templatefile Tester Render it before you apply it Terraform Resource Count Calculator How many objects, not how many blocks Terraform count to for_each Converter With the moved blocks it needs Terraform moved Block Generator Rename without destroying Terraform state mv Command Builder No plan, no undo Terraform target Flag Builder And why to stop using it Terraform outputs.tf Generator Outputs are not sensitive by default Terraform Remote State Data Source Generator It grants read of the whole state Terraform Provider Block Generator docker is not hashicorp/docker Terraform .gitignore Generator and Checker .terraform* eats the lock file Terraform to OpenTofu Migration Checker The state is the part to watch Terraform tfvars to JSON Converter The JSON file wins Terraform Version Constraint Parser What ~> actually allows Terraform Resource Address Parser Quote it before the shell eats it Terraform cidrsubnet Calculator newbits is added, not the target Terraform Import Block Generator The id is not the name Terraform Lock File Viewer Why CI fails and your laptop does not Terraform Variables Checker A missing value hangs CI Terraform tfvars to Env Vars Converter Lists and maps have to be JSON Terraform Deprecated Syntax Checker What a current Terraform rejects Terraform State File Viewer Read it without uploading it Terraform Plan JSON Viewer It is not redacted Terraform Module Source Validator version only works for the registry Terraform Backend Config Decoder Is state actually locked? Terraform Naming Convention Validator A hyphen makes a resource unreferenceable

Elsewhere on the site