I have the below body used in a resource in terraform to deploy logic app:
body = jsonencode({
properties = {
definition = jsondecode(templatefile(templ.json,
{
schedHour = tostring(var.schedule_hour) #is a string type;
functUri = "https://abc"
reqBody = jsonencode(var.func_parameters) #is an object type;
}))
state = "Enabled"
}
})
The problem is when I want to deploy that JSON template where I reference the reqBody value as below:
"inputs": {
"subscribe": {
"body": "${reqBody}",
"method": "POST",
"uri": "${functUri}"
},
"unsubscribe": {}
}
It results the error when I try terraform apply:
Error: Error in function call
on ../modules/logic-app/main.tf line 21, in resource "azapi_resource" "logic_app_workflow":
21: definition = jsondecode(templatefile(templ.json,
22: {
23: scheduleHour = tostring(var.schedule_hour)
24: functUri = "https://abc"
27: reqBody = jsonencode(var.func_parameters)
28: }))
├────────────────
│ while calling jsondecode(str)
│ var.func_parameters is object with 1 attribute "pipeline"
│ var.schedule_hour is 5
Call to function "jsondecode" failed: invalid character 'p' after object key:value pair.
It seems the problem is on that object variable reqBody which is as below defined:
variable "func_parameters" {
type = object({
pipeline = object({
calc_date = string
....
})
})
}
One possible FIX but wished/right one is to use in json template the reference as:
"body" : ${reqBody} #without "" but it makes to be an invalid json template but it works to be deployed;
I tried move the reqBody param in a separately block called parameters but not working. it should be in definition, as azapi_resource require.
For the "uri" : "${fctUri}" works, it’s fine referenced and shows what is needed (it is a string), but the problem remains on that object var;
ref: https://github.com/michaelstephensonuk/CodeSnippets/blob/main/LogicApp-Consumption-WithTerraform/Res.LogicApp.Demo-LogicApp-2.tf
I tried with jsondecode for that object var and the error is saying it should be a string;
somehow it requires a string as for the rest variables: I tried with decode for that object
on ../modules/logic-app/main.tf line 27, in resource "azapi_resource" "logic_app_workflow":
27: requestBody = jsondecode(var.func_parameters)
├────────────────
│ while calling jsondecode(str)
│ var.func_parameters is a object
Invalid value for "str" parameter: string required.
the rest are strings and they works fine;
2
Answers
You have to break your code and add outputs to see what is going on…
all those nested functions are just obscuring the issue, use multiple local variables, like:
the json I’m using:
yes that will error out but we also get some output:
We can see that is not valid json there are unescaped quotes there
To get around the unescaped quotes you need to do:
replace(jsonencode(var.func_parameters), """, "\"")
full code:
Generating valid JSON by concatenating strings together is complicated to perform correctly, because JSON expects values to be escaped in a specific way, etc.
If you instead use
jsonencode
to produce the JSON from your template, you can be sure that the result will be valid JSON because Terraform itself will create the JSON string:For this template, the entire template is a single interpolation sequence
${ ... }
which contains just a call tojsonencode
. The result ofjsonencode
is a JSON representation of its argument, and so the template result will be a JSON representation of the result of the Terraform expression passed to that function.Because
jsonencode
always produces valid JSON,jsondecode
of that result should therefore always succeed.