Search code examples
azureazure-resource-managerazure-rm-template

How to convert an array into properties of one object in an ARM template?


I am looking for a way to convert an array (e.g. of strings) into one object, where the properties are generated from the array values.

Use case: I want to generate a tags object with links to resources, based on a list of resource names. I need to do this, to link App Service resources to an Application Insights resource.

The list of resources could be supplied using a parameter:

"parameters": {
  "appServices": {
    "type": "array",
    "metadata": {
      "description": "Names of app services to link this application insights resource to via hidden tags"
    }
  }
}

Sample input:

['appName1', 'appName2', 'appName3']

Sample output:

"tags":
{
  "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', 'appName1'))]": "Resource",
  "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', 'appName2'))]": "Resource",
  "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', 'appName3'))]": "Resource"
}

I know you can use copy to loop over arrays but that will create an array of objects and not a single object (which is required for tags), for example:

[
{
  "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', 'appName1'))]": "Resource"
},
{
  "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', 'appName2'))]": "Resource"
},
{
  "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', 'appName3'))]": "Resource"
}
]

It would be possible to use union to merge those objects again, but that function requires you to hardcode the objects you want to merge, so it does not work when you have an input with variable length.

What I am looking for is a way to do this in a dynamic way.


Solution

  • There is no direct option to convert array to object. But here's a hack to achieve what you need. This will work for array of any length.

    Steps:

    1. append hidden-link text to service names
    2. convert array to string
    3. replace necessary symbols and make it a valid json string.
    4. use json() to convert string to object
    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "appServices": {
          "type": "array",
          "metadata": {
            "description": "Names of app services to link this application insights resource to via hidden tags"
          },
          "defaultValue": [ "appName1", "appName2", "appName3" ]
        }
      },
      "functions": [],
      "variables": {
        "copy": [
          {
            "name": "as",
            "count": "[length(parameters('appServices'))]",
            "input": "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', parameters('appServices')[copyIndex('as')]))]"
          }
        ],
        "0": "[string(variables('as'))]",
        "1": "[replace(variables('0'), '[', '{')]",
        "2": "[replace(variables('1'), '\",', '\":\"Resource\",')]",
        "3": "[replace(variables('2'), '\"]', '\":\"Resource\"}')]"
      },
      "resources": [],
      "outputs": {
        "op1": {
          "type": "object",
          "value": "[json(variables('3'))]"
        }
      }
    }
    

    enter image description here