Kaguei Nakueka
Kaguei Nakueka

Reputation: 1108

Issue with BOOL type DynamoDB Item

I am trying to create a BOOL type attribute to a table as follows:

resource "aws_dynamodb_table_item" "items" {
    table_name = aws_dynamodb_table.dynamodb-table.name
    hash_key = aws_dynamodb_table.dynamodb-table.hash_key
    range_key = aws_dynamodb_table.dynamodb-table.range_key

    for_each = {
        "0" = {
            location = "Madrid",
            coordinates = ["40.49", "-3.56"],
            visible = "false",
            destinations = ["0", "4"]
        },
        "1" = {
            location = "Mexico City",
            coordinates = ["52.36", "13.51"],
            visible = "true",
            destinations = ["1", "4"]
        },

    }

    item = <<EOF
    {
        "id": { "N": "${each.key}"},
        "location": {"S" : "${each.value.location}"},
        "coordinates": {"NS": ${jsonencode(each.value.coordinates)}},
        "destinations": {"NS": ${jsonencode(each.value.destinations)}},
        "visible": {"BOOL": "${each.value.visible}"}
    }
    EOF
}

But I get the following error:

Error: Invalid format of "item": Decoding failed: json: cannot unmarshal string into Go struct field AttributeValue.BOOL of type bool

According to the AWS documentation the attribute value seems right:

BOOL
An attribute of type Boolean. For example:
"BOOL": true
Type: Boolean
Required: No

If try to save as S (String), it works.

What am I doing wrong in this example?

Upvotes: 3

Views: 3054

Answers (2)

Martin Atkins
Martin Atkins

Reputation: 74124

This sort of unexpected behavior is a common result of trying to build JSON strings by string concatenation. You included quotes in the template and so Terraform retained the quotes, making the boolean value appear in the result as if it were a string.

To make this more readable and to reduce the chances of that sort of mistake, you should construct the entire JSON value using jsonencode, rather than just small portions of it:

  item = jsonencode({
    id           = { N = each.key }
    location     = { S = each.value.location }
    coordinates  = { NS = each.value.coordinates }
    destinations = { NS = each.value.destinations }
    visible      = { BOOL = each.value.visible }
  })

This pattern makes it Terraform's job to convert the entire value to valid JSON, using the type-mapping rules described in the jsonencode documentation. In particular, that function knows to convert a Terraform bool value into a JSON Bool value, getting the result you needed here without the errant extra quotes. It will also ensure that the id and location values are properly escaped to be JSON strings, whereas your original example would've failed if either of those contained any characters that JSON considers to be "special".

Upvotes: 3

Kaguei Nakueka
Kaguei Nakueka

Reputation: 1108

"visible": {"BOOL": ${each.value.visible}}

without quotes! :-p

Upvotes: 3

Related Questions