2

My variable is the following in powershell:

$lcr=@{"tierToCool"=@{"daysAfterModificationGreaterThan"=1};"tierToArchive"=@{"daysAfterModificationGreaterThan"=2}}

Then when I run the template using an az cli command to pass the variable as an object into my arm template:

az deployment group create --subscription <hidden> --resource-group <hidden> --template-file <hidden> --parameters lcr=$lcr

I get the following error:

Failed to parse JSON: System.Collections.Hashtable

Error Detail: Expecting value: line 1 column 1 (char 0)

Is there something wrong with the way I'm passing the parameter into the template or the way I'm formatting it? Any help is greatly appreciated.

user13696433
  • 93
  • 3
  • 11
  • Looks like `az` is expecting JSON. Try `... --parameters lcr=$($lcr |ConvertTo-Json)` – Mathias R. Jessen Aug 17 '21 at 16:45
  • Failed to parse JSON: { Error detail: expecting property name enclosed in double quotes – user13696433 Aug 17 '21 at 17:28
  • 1
    `--parameters` requires JSON only - either do `--parameters ($lcr|ConvertTo-Json)` or just convert your hash table to a json string manually. If 'lcr' is a parameter name too, set it as one of the hash table entries like `$lcr=@{'lcr'=@{'tierToCool'=...}}`. Check out the az group deployment page for more examples: https://learn.microsoft.com/en-us/cli/azure/group/deployment?view=azure-cli-latest – Cpt.Whale Aug 17 '21 at 17:53

1 Answers1

3

Building on the helpful comments:

  • az, the Azure CLI, requires JSON as the --parameters arguments, i.e., a JSON string, not a hashtable.

    • It generally makes no sense to pass a hashtable as an argument to an external program, because doing so sends its string representation, which is - unhelpfully - the type name, 'System.Collections.Hashtable'
  • While --parameters (@{ lcr = $lcr } | ConvertTo-Json -Compress) should be enough to send the JSON representation of your hashtable, the sad reality is that, as of PowerShell 7.1, you additionally need to \-escape the embedded " characters, due to a long-standing bug in argument-passing to external programs.

    • The most robust way to do this is (if there are no escaped " in the string, -replace '"', '\"' is enough):

      --parameters ((@{ lcr = $lcr } | ConvertTo-Json -Compress) -replace '([\\]*)"', '$1$1\"')
      
    • If you have a JSON string literal or JSON string stored in variable, use the following to pass it to an external program (if the string is stored in a variable $var, replace '{ "foo": "bar" }' with $var):

      someProgram ... ('{ "foo": "bar" }' -replace '([\\]*)"', '$1$1\"')
      
    • See this answer for more information.

Therefore:

az deployment group create --subscription <hidden> --resource-group <hidden> --template-file <hidden> --parameters ((@{ lcr = $lcr } | ConvertTo-Json -Compress) -replace '([\\]*)"', '$1$1\"')

A general ConvertTo-Json pitfall: You may need to use the -Depth parameter for full to-JSON serialization, depending on how deeply nested your object graph is (not needed with your sample input) - see this post.

mklement0
  • 382,024
  • 64
  • 607
  • 775