jsonencode / jsondecode — JSON文字列をHCLで扱う関数

1. 概要

  • jsonencode — HCLの値をJSON文字列に変換する
  • jsondecode — JSON文字列をHCLの値に変換する
  • IAMポリシーへの適用(最頻出パターン)
  • yamlencode / yamldecodeとの比較
  • file()と組み合わせた外部JSONファイルの読み込み

IAMポリシーやKubernetesマニフェストなど、JSON形式の文字列が必要な場面でTerraformのjsonencodeを使うと、HCLの構文チェックを受けながらJSONを書けます。ダブルクォートのエスケープも不要です。


2. jsonencode — HCLの値をJSON文字列に変換する

jsonencode(value)は、HCLの値(map・list・string・numberなど)をJSON文字列に変換します。

# terraform consoleで確認
> jsonencode({ "key" = "value" })
"{\"key\":\"value\"}"

> jsonencode(["a", "b", "c"])
"[\"a\",\"b\",\"c\"]"

> jsonencode({ name = "web", port = 80 })
"{\"name\":\"web\",\"port\":80}"

IAMポリシーへの適用(最重要パターン)

aws_iam_policyリソースはpolicy引数にJSON文字列を要求します。jsonencodeを使うとHCL形式で書けます。

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

resource "aws_s3_bucket" "app_data" {
  bucket = "${var.environment}-myapp-data"

  tags = {
    Name        = "${var.environment}-myapp-data"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# ✅ jsonencodeを使うとHCL形式でIAMポリシーを書ける
resource "aws_iam_policy" "s3_read" {
  name        = "${var.environment}-s3-read"
  description = "S3バケットへの読み取りポリシー"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "AllowS3Read"
        Effect   = "Allow"
        Action   = ["s3:GetObject", "s3:ListBucket"]
        Resource = [
          aws_s3_bucket.app_data.arn,
          "${aws_s3_bucket.app_data.arn}/*"
        ]
      }
    ]
  })

  tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

jsonencodeなしで書いた場合(ヒアドキュメント):

# ❌ ヒアドキュメントはTerraformの構文チェックが効かない
policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "${aws_s3_bucket.app_data.arn}/*"
    }
  ]
}
EOF

jsonencodeではTerraformがHCLとして解析するため、シンタックスエラーをplan時に検出できます。ヒアドキュメントは文字列として扱われるため、JSONのミスを実行時まで発見できません。


3. ECSタスク定義へのjsonencode

ECSのコンテナ定義もJSON文字列で渡す必要があります。

resource "aws_ecs_task_definition" "app" {
  family                   = "${var.environment}-app"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = "256"
  memory                   = "512"

  container_definitions = jsonencode([
    {
      name      = "app"
      image     = "nginx:latest"
      essential = true
      portMappings = [
        {
          containerPort = 80
          protocol      = "tcp"
        }
      ]
      logConfiguration = {
        logDriver = "awslogs"
        options = {
          "awslogs-group"         = "/ecs/${var.environment}-app"
          "awslogs-region"        = "ap-northeast-1"
          "awslogs-stream-prefix" = "app"
        }
      }
    }
  ])
}

4. jsondecode — JSON文字列をHCLの値に変換する

jsondecode(string)は、JSON文字列をHCLの値(map・list等)に変換します。外部ファイルやdataブロックから取得したJSON文字列を操作するときに使います。

# terraform consoleで確認
> jsondecode("{\"key\": \"value\"}")
{
  "key" = "value"
}

> jsondecode("[1, 2, 3]")
[1, 2, 3]

外部JSONファイルの読み込み

# policy.json(外部ファイル)
# {
#   "Version": "2012-10-17",
#   "Statement": [...]
# }

locals {
  # file()でJSONファイルを読み込み、jsondecodeでHCLに変換
  policy_doc = jsondecode(file("${path.module}/policy.json"))
}

# 変換後のmapから値を取り出す
output "policy_version" {
  value = local.policy_doc["Version"]  # → "2012-10-17"
}

SSMパラメータのJSON値を解析する

data "aws_ssm_parameter" "config" {
  name = "/myapp/config"
  # 値が JSON 文字列 '{"db_host": "xxx", "port": 5432}' の場合
}

locals {
  config = jsondecode(data.aws_ssm_parameter.config.value)
  db_host = local.config["db_host"]
  db_port = local.config["port"]
}

5. yamlencode / yamldecodeとの比較

Terraform 0.13以降ではyamlencodeyamldecodeも利用できます。

# yamlencode: HCL → YAML文字列
> yamlencode({ name = "web", port = 80 })
"name: web\nport: 80\n"

# yamldecode: YAML文字列 → HCL
> yamldecode("name: web\nport: 80\n")
{
  "name" = "web"
  "port" = 80
}

Kubernetes(Helm)やAnsible連携など、YAML形式が必要な場合はyamlencodeが便利です。それ以外(IAMポリシー、ECSなど)はjsonencodeを使います。


6. 関連記事


7. まとめ

  • jsonencode(value) — HCLの値(map/list)をJSON文字列に変換。IAMポリシー・ECSタスク定義に最適
  • jsondecode(string) — JSON文字列をHCLの値に変換。外部ファイルやdataブロックのJSON解析に使う
  • jsonencodeはヒアドキュメントよりもTerraformの構文チェックが効くため品質が高い
  • YAMLが必要な場合はyamlencode / yamldecodeを使う
  • IAMポリシードキュメントはaws_iam_policy_documentデータソースでも書けるが、jsonencodeはよりシンプル

動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/jsonencode