Can we use ternary operator within string template or jsonencode

Can we use ternary operator within string template or jsonecode function.
example:

event_pattern = jsonencode({{
    "detail-type" : ["Step Functions Execution Status Change"],
    "detail"      : {
    "stateMachineArn" : ${var.sfn_arn} != "" ?  [${aws_sfn_state_machine.myapp.arn}, ${var.yourapp_sfn_arn}] : [${aws_sfn_state_machine.myapp.arn}],
    "status"          : ["FAILED"]
  },
    "source" : ["aws.states"]
  })

OR in string template:

event_pattern = <<-EOF
{
    "detail-type" : ["Step Functions Execution Status Change"],
    "detail"      : {
    "stateMachineArn" : ${var.sfn_arn} != "" ?  [${aws_sfn_state_machine.myapp.arn}, ${var.yourapp_sfn_arn}] : [${aws_sfn_state_machine.myapp.arn}],
    "status"          : ["FAILED"]
  },
    "source" : ["aws.states"]
}
EOF

Hi @gtwuser,

The argument to jsonencode is just a normal Terraform expression, with all of the same features as you could use when assigning a value directly to event_pattern. So you can use the conditional operator as part of that expression – it doesn’t really have anything to do with jsonencode – but you will need to use valid expression syntax:

  event_pattern = jsonencode({
    stateMachineArn = (
      var.sfn_arn != "" ?
      [aws_sfn_state_machine.myapp.arn, var.sfn_arn] :
      [aws_sfn_state_machine.myapp.arn]
    )
  })

I wrapped the expression over multiple lines to make it easier to read, but that’s just a style thing and not required for correctness.

It might interest you that the compact function is a terser way to deal with this common problem of eliminating null and empty-string elements from a list or tuple, so you could write the above like this instead if you like:

  event_pattern = jsonencode({
    stateMachineArn = compact([
      aws_sfn_state_machine.myapp.arn,
      var.sfn_arn,
    ])
  })

The compact function will ignore the second element if it’s "", thereby producing the same result as the conditional expression.


The string template syntax is a little different in that it uses interpolation sequences (${}) and template directives (%{}) as a way to differentiate the literal string parts from the expression parts. Although I would never recommend generating JSON using string templates, here’s an example of using the if template directive as a template-based equivalent to a conditional expression when you are generating arbitrary text, rather than JSON:

  example = <<-EOT
    blah: %{ if var.example != "" ~}
    ${var.example}
    %{ else ~}
    default-thing-to-include-instead
    %{ endif ~}
  EOT

It’s also valid to use a conditional expression inside an interpolation sequence, because any valid expression is allowed in an interpolation sequence. That approach can potentially be more concise if you don’t actually need to do any further interpolation/directives inside either of the results:

  example = <<-EOT
    blah: ${ var.example != "" ? var.example : "default-thing-to-include-instead" }
  EOT

Overall, the main thing to keep in mind is that these language features are largely independent of one another: the argument to jsonencode and the contents of a ${} interpolation in a string template are both just arbitrary expressions, and so you can write any valid expression there and expect it to behave the same as it would in any other context where expressions are expected.

Thank you for your detailed answer it helps a lot… I did exactly as per your suggestion … But now I feel im still missing something here would you please let me know why is this issue coming up with the below code

212:   event_pattern = <<-EVNT_DEF
 213: {
 214:   "detail-type" = ["Step Functions Execution Status Change"],
 215:   "detail"      = {
 216:   "stateMachineArn" = ${var.sfn_arn != "" ? [aws_sfn_state_machine.myapp.arn, var.sfn_arn] : [aws_sfn_state_machine.myapp.arn]}
 217:   "status"          = ["FAILED"]
 218:   },
 219:   "source" = ["aws.states"]
 220: }
 221: EVNT_DEF
    ├────────────────
    │ aws_sfn_state_machine.myapp.arn is a string
    │ var.sfn_arn is ""

Cannot include the given value in a string template: string required.

As I said in my previous message, I do not recommend generating JSON with string templates.

However, if you insist then you will need to make sure that everything you interpolate is a string containing a valid JSON fragment. You have tried to interpolate a list, which is impossible because a string cannot contain a list.

Thank you, got it working using jsonecode over the list. Incase someone needs to know the code :

event_pattern = <<-EVNT_DEF
{
  "detail-type" : ["Step Functions Execution Status Change"],
  "detail"      : {
  "stateMachineArn" : ${var.sfn_arn != "" ? jsonencode([aws_sfn_state_machine.myapp.arn, var.sfn_arn]) : jsonencode([aws_sfn_state_machine.myapp.arn])},
  "status"          : ["FAILED"]
  },
  "source" : ["aws.states"]
}
EVNT_DEF