user13696433
user13696433

Reputation: 143

How do you pass an object parameter into a json arm template as a hashtable?

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.

Upvotes: 2

Views: 2951

Answers (1)

mklement0
mklement0

Reputation: 440122

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.

Upvotes: 3

Related Questions