Skip to content

Encoding Functions

Encoding functions handle conversion between different data formats, including JSON and CSV.

Decodes CSV-formatted data into a list of maps.

csvdecode(string)

Parameters:

  • string - CSV-formatted string

Returns: List of maps representing rows

Example:

csvdecode("name,age\nAlice,30\nBob,25")
# Returns: [
# {name = "Alice", age = "30"},
# {name = "Bob", age = "25"}
# ]
csvdecode("host,port\nweb,80\napi,8080")
# Returns: [
# {host = "web", port = "80"},
# {host = "api", port = "8080"}
# ]

Parses a JSON string into HCL values.

jsondecode(string)

Parameters:

  • string - JSON-formatted string

Returns: Decoded HCL value (map, list, string, number, bool)

Example:

jsondecode('{"name": "lab", "port": 8080}')
# Returns: {name = "lab", port = 8080}
jsondecode('["a", "b", "c"]')
# Returns: ["a", "b", "c"]
jsondecode('"hello"')
# Returns: "hello"
jsondecode('42')
# Returns: 42
jsondecode('true')
# Returns: true

Converts HCL values to JSON format.

jsonencode(value)

Parameters:

  • value - Any HCL value to encode

Returns: JSON-formatted string

Example:

jsonencode({name = "lab", port = 8080})
# Returns: '{"name":"lab","port":8080}'
jsonencode(["a", "b", "c"])
# Returns: '["a","b","c"]'
jsonencode("hello")
# Returns: '"hello"'
jsonencode(42)
# Returns: '42'
jsonencode(true)
# Returns: 'true'
# Parse external configuration
locals {
config_json = file("./config.json")
config = jsondecode(local.config_json)
# Access nested values
api_url = local.config.api.url
timeout = local.config.settings.timeout
}
# Generate configuration files
resource "template" "app_config" {
source = jsonencode({
database = {
host = var.db_host
port = var.db_port
name = var.db_name
}
features = var.enabled_features
debug = var.debug_mode
})
destination = "./app-config.json"
}
# Prepare data for API requests
resource "http" "webhook" {
url = "https://api.example.com/webhook"
method = "POST"
body = jsonencode({
event = "lab_started"
user_id = var.user_id
metadata = {
lab_name = var.lab_name
started_at = var.start_time
}
})
headers = {
"Content-Type" = "application/json"
}
}
# Parse API response
locals {
api_response = file("./api-response.json")
response_data = jsondecode(local.api_response)
user_id = local.response_data.user.id
}
# Import user data from CSV
locals {
users_csv = file("./users.csv")
users = csvdecode(local.users_csv)
}
# Create resources from CSV data
resource "container" "user_workspace" {
for_each = {
for user in local.users : user.username => user
}
image {
name = "workspace:latest"
}
environment = {
USERNAME = each.value.username
EMAIL = each.value.email
ROLE = each.value.role
USER_ID = each.value.id
}
}
# Process server inventory from CSV
locals {
servers_csv = csvdecode(file("./servers.csv"))
# CSV format: hostname,ip,role,region
}
resource "template" "inventory" {
source = jsonencode({
servers = [
for server in local.servers_csv : {
hostname = server.hostname
ip = server.ip
role = server.role
region = server.region
}
]
})
destination = "./inventory.json"
}
# Build configuration dynamically
locals {
base_config = {
app_name = var.app_name
version = var.app_version
}
environment_config = var.environment == "production" ? {
log_level = "warn"
debug = false
replicas = 3
} : {
log_level = "debug"
debug = true
replicas = 1
}
final_config = merge(local.base_config, local.environment_config)
}
resource "template" "config" {
source = jsonencode(local.final_config)
destination = "./runtime-config.json"
}
# Transform CSV to JSON
locals {
products_csv = csvdecode(file("./products.csv"))
# CSV columns: name,price,category,in_stock
products_json = {
products = [
for product in local.products_csv : {
name = product.name
price = tonumber(product.price)
category = product.category
available = product.in_stock == "true"
}
]
}
}
resource "template" "products" {
source = jsonencode(local.products_json)
destination = "./products.json"
}
# Merge multiple configuration sources
locals {
# Default configuration
default_config = jsondecode(file("./config/default.json"))
# Environment-specific configuration
env_config_file = "./config/${var.environment}.json"
env_config = fileexists(env_config_file) ?
jsondecode(file(env_config_file)) : {}
# User overrides
user_overrides = var.config_overrides != "" ?
jsondecode(var.config_overrides) : {}
# Final merged configuration
merged_config = merge(
local.default_config,
local.env_config,
local.user_overrides
)
}
resource "template" "final_config" {
source = jsonencode(local.merged_config)
destination = "./app-config.json"
}
# Generate metadata for lab resources
locals {
lab_metadata = {
lab = {
name = var.lab_name
version = var.lab_version
created_at = var.created_at
}
resources = {
containers = length([for r in local.resources : r if r.type == "container"])
networks = length([for r in local.resources : r if r.type == "network"])
volumes = length([for r in local.resources : r if r.type == "volume"])
}
configuration = {
debug_mode = var.debug_enabled
log_level = var.log_level
feature_flags = var.feature_flags
}
}
}
resource "template" "metadata" {
source = jsonencode(local.lab_metadata)
destination = "./lab-metadata.json"
}
# Handle encrypted configuration
locals {
# Read encrypted config (base64 encoded JSON)
encrypted_config = var.secret_config
decrypted_json = base64decode(local.encrypted_config)
secret_config = jsondecode(local.decrypted_json)
}
resource "container" "app" {
environment = {
DATABASE_URL = local.secret_config.database.url
API_KEY = local.secret_config.api.key
# Store the full config as JSON
CONFIG_JSON = jsonencode(local.secret_config)
}
}
  1. Validate JSON Input: Check for parsing errors

    locals {
    # Safely decode with error handling
    config = try(jsondecode(var.json_input), {
    error = "Invalid JSON input"
    })
    }
  2. Use Appropriate Data Types: Consider numeric conversions

    locals {
    # Convert string numbers from CSV to actual numbers
    users = [
    for user in csvdecode(file("users.csv")) : {
    name = user.name
    age = tonumber(user.age)
    active = user.active == "true"
    }
    ]
    }
  3. Handle Missing Files: Check file existence

    locals {
    config = exists("./config.json") ?
    jsondecode(file("./config.json")) :
    {default = true}
    }
  4. Format JSON Output: Use proper indentation for readability

    resource "template" "readable_config" {
    # Note: jsonencode produces compact JSON
    # For pretty-printed JSON, you may need external tools
    source = jsonencode(local.config)
    destination = "./config.json"
    }