如何使用Terraform csvdecode读取带双引号的字符串值?
读取CSV中转义的JSON并写入DynamoDB问题
问题场景
有如下内容的CSV文件:
id,value 123,{"M":{"name_1":{"S":"value_1"}, "name_2":{"S":"value_2"}}}
尝试用以下Terraform代码读取该CSV并向DynamoDB写入记录,但无法正常运行:
locals { custom_data = csvdecode(file("${path.module}/../custom_data.csv")) } resource "aws_dynamodb_table_item" "custom_table_item" { for_each = {for row in local.custom_data : row.id => row} table_name = aws_dynamodb_table.custom_table.name hash_key = aws_dynamodb_table.custom_table.hash_key item = jsonencode({ "id" : { "S" : each.value.id }, "value" : jsondecode(each.value.value) }) lifecycle { ignore_changes = [item] } }
核心问题:CSV中的双引号被转义为",无法让jsondecode生成正确的JSON结构。
解决方案
问题根源是CSV里的"是HTML实体转义的双引号,csvdecode不会自动解析这类转义,所以需要先将"替换为真实的双引号,再执行JSON解析。
方案1:在resource中直接处理
修改item字段的value解析逻辑,先用replace替换转义字符:
resource "aws_dynamodb_table_item" "custom_table_item" { for_each = {for row in local.custom_data : row.id => row} table_name = aws_dynamodb_table.custom_table.name hash_key = aws_dynamodb_table.custom_table.hash_key item = jsonencode({ "id" : { "S" : each.value.id }, "value" : jsondecode(replace(each.value.value, """, "\"")) }) lifecycle { ignore_changes = [item] } }
方案2:在locals中提前预处理数据
如果有多行数据,推荐在locals里统一处理,让resource代码更简洁:
locals { custom_data = [ for row in csvdecode(file("${path.module}/../custom_data.csv")) : { id = row.id value = jsondecode(replace(row.value, """, "\"")) } ] } resource "aws_dynamodb_table_item" "custom_table_item" { for_each = {for row in local.custom_data : row.id => row} table_name = aws_dynamodb_table.custom_table.name hash_key = aws_dynamodb_table.custom_table.hash_key item = jsonencode({ "id" : { "S" : each.value.id }, "value" : each.value.value }) lifecycle { ignore_changes = [item] } }
原理说明
replace(each.value.value, """, "\"")会把CSV中所有的"替换为标准双引号,此时jsondecode就能正确识别JSON格式,生成DynamoDB所需的Map结构,最终写入到数据库中。
内容的提问来源于stack exchange,提问作者João Pedro Schmitt
相关产品推荐
相关产品推荐

