Call to function "jsondecode" failed: invalid character 'e' in literal null (expecting 'u')

Hello All,

am using csv decode to create the resources, Currently, I am able to create resources with one to one mapping.

> { for name in local.confluent_values : "${name.service_account}:${name.environment}" => name }
{
  "first-test:dev-b1" = {
    "service_account" = "first-test"
    "environment" = "dev-b1"
    "topic_name" = "new-test-topic"
  }

how should I be modifying the resource block below to accept list of topics names as inputs from csv decode. kindly let me know if this is possible.

{
  "first-test:dev-b1" = {
    "environment" = "dev-b1"
    "service_account" = "first-test"
    "topic_name" = "new-test-topic,new-test-topic-2,new-test-topic-3"
  }
module "confluent_topic" {
  source       = "./modules/confluent_topic"
  for_each     = { for name in local.confluent_values : "${name.service_account}:${name.topic_name}:${name.environment}" => name }
  topic_name   = "${each.value.environment}-${each.value.topic_name}"
  cluster_name = each.value.cluster_name
}

I used [""new-test-topic"",""new-test-topic-2"",""new-test-topic-3""] to represent the csv in list format, then I tried using jsondecode and pass the values to the resource block, but am seeing an error in the function call…

tolist(jsondecode("[\"new-test-topic\",\"new-test-topic-2\",\"new-test-topic-3\"]"))
tolist([
  "new-test-topic",
  "new-test-topic-2",
  "new-test-topic-3",
])
Error: Error in function call
│ 
│   on main.tf line 25, in module "confluent_topic":
│   25:   topic_name   = tolist(jsondecode(each.value.topic_name))
│     ├────────────────
│     │ while calling jsondecode(str)
│     │ each.value.topic_name is "new-test-topic-1"
│ 
│ Call to function "jsondecode" failed: invalid character 'e' in literal null (expecting 'u').
╵

╷
│ Error: Error in function call
│ 
│   on main.tf line 25, in module "confluent_topic":
│   25:   topic_name   = tolist(jsondecode(each.value.topic_name))
│     ├────────────────
│     │ while calling jsondecode(str)
│     │ each.value.topic_name is "new-test-topic"
│ 
│ Call to function "jsondecode" failed: invalid character 'e' in literal null (expecting 'u').
╵

╷
│ Error: Error in function call
│ 
│   on main.tf line 25, in module "confluent_topic":
│   25:   topic_name   = tolist(jsondecode(each.value.topic_name))
│     ├────────────────
│     │ while calling jsondecode(str)
│     │ each.value.topic_name is "new-test-topic-1"
│ 
│ Call to function "jsondecode" failed: invalid character 'e' in literal null (expecting 'u').
╵

To fix your issue, ensure your CSV has the topic_name values formatted as JSON arrays for entries with multiple topics. Then, in your Terraform code, use the try function with jsondecode to handle both single and multiple topic names. Adjust the topic_name assignment in your confluent_topic module to:

hclCopy code

topic_name = try(jsondecode(each.value.topic_name), [each.value.topic_name])

This will decode the topic names if they are in JSON format or fall back to a single-item list if not. Ensure your module can handle topic_name as a list.

Hello @rtwolfe , thanks for the inputs, unfortunately it did not work, could you please let me know if its possible to create unique key in for expression from a list of inputs in csv file?

eg {
    "new-test-topic:dev-b1"= {
    "environment" = "dev-b1"
    "topics_name" = "new-test-topic"
  }
}

currently am getting the below format.

> { for name in local.confluent_values : "${name.topics_name}:${name.environment}" => name }
{
  "[\"new-test-topic\",\"new-test-topic-3\"]:dev-b1" = {
    "environment" = "dev-b1"
    "topics_name" = "[\"new-test-topic\",\"new-test-topic-3\"]"
  }
}
╷
│ Error: Error in function call
│ 
│   on main.tf line 26, in module "confluent_topic":
│   26:   topic_name   = try(jsondecode(each.value.topic_name),[each.value.topic_name])
│     ├────────────────
│     │ while calling try(expressions...)
│     │ each.value is object with 11 attributes
│ 
│ Call to function "try" failed: no expression succeeded:
│ - Unsupported attribute (at main.tf:26,43-54)
│   This object does not have an attribute named "topic_name".
│ - Unsupported attribute (at main.tf:26,67-78)
│   This object does not have an attribute named "topic_name".
│ 
│ At least one expression must produce a successful result.
╵