Skip to content

Instantly share code, notes, and snippets.

@tsoe77
Created March 4, 2025 15:30
Show Gist options
  • Select an option

  • Save tsoe77/6cbd6006decfe4fdcea706da96d6cd8d to your computer and use it in GitHub Desktop.

Select an option

Save tsoe77/6cbd6006decfe4fdcea706da96d6cd8d to your computer and use it in GitHub Desktop.
A python script to convert JSON to HCL
#!/usr/bin/env python3
# json2hcl.py - Convert JSON to Terraform HCL
import json
import sys
import re
import argparse
from typing import Any, Dict, List, Union
def format_value(value: Any) -> str:
"""Format a value according to HCL syntax rules."""
if isinstance(value, bool):
return str(value).lower()
elif isinstance(value, (int, float)):
return str(value)
elif isinstance(value, str):
# Escape quotes and handle multiline strings
escaped = value.replace("\\", "\\\\").replace('"', '\\"')
if "\n" in escaped:
return "<<EOT\n{}\nEOT".format(escaped)
else:
return f'"{escaped}"'
elif value is None:
return "null"
else:
raise ValueError(f"Unsupported type: {type(value)}")
def json_to_hcl(data: Union[Dict, List], indent: int = 0) -> str:
"""Convert a JSON object to HCL format."""
result = []
spaces = " " * indent
if isinstance(data, dict):
for key, value in data.items():
if isinstance(value, dict):
result.append(f"{spaces}{key} = {{")
result.append(json_to_hcl(value, indent + 2))
result.append(f"{spaces}}}")
elif isinstance(value, list):
if all(isinstance(item, dict) for item in value):
for item in value:
result.append(f"{spaces}{key} {{")
result.append(json_to_hcl(item, indent + 2))
result.append(f"{spaces}}}")
else:
formatted_items = [format_value(item) for item in value]
result.append(f"{spaces}{key} = [{', '.join(formatted_items)}]")
else:
result.append(f"{spaces}{key} = {format_value(value)}")
elif isinstance(data, list):
if all(isinstance(item, dict) for item in data):
for item in data:
result.append(f"{spaces}{{")
result.append(json_to_hcl(item, indent + 2))
result.append(f"{spaces}}}")
else:
formatted_items = [format_value(item) for item in data]
result.append(f"{spaces}[{', '.join(formatted_items)}]")
return "\n".join(result)
def main():
parser = argparse.ArgumentParser(description="Convert JSON to Terraform HCL")
parser.add_argument(
"input_file",
nargs="?",
type=argparse.FileType("r"),
default=sys.stdin,
help="Input JSON file (default: stdin)",
)
parser.add_argument(
"output_file",
nargs="?",
type=argparse.FileType("w"),
default=sys.stdout,
help="Output HCL file (default: stdout)",
)
parser.add_argument(
"-v", "--variable", help="Wrap output in a variable with the given name"
)
args = parser.parse_args()
try:
data = json.load(args.input_file)
hcl = json_to_hcl(data)
if args.variable:
hcl = f"{args.variable} = {{\n{json_to_hcl(data, 2)}\n}}"
args.output_file.write(hcl)
args.output_file.write("\n")
except json.JSONDecodeError as e:
print(f"Error decoding JSON: {e}", file=sys.stderr)
return 1
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return 1
finally:
if args.input_file != sys.stdin:
args.input_file.close()
if args.output_file != sys.stdout:
args.output_file.close()
return 0
if __name__ == "__main__":
sys.exit(main())
# Basic usage (read from file, output to stdout)
# python json2hcl.py input.json
# Read from stdin, output to file
# cat input.json | python json2hcl.py > output.tf
# Wrap in a variable
# python json2hcl.py input.json -v helm_values > output.tf
# Full example with input and output files
# python json2hcl.py input.json output.tf -v helm_values
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment