Format Function use with an array of Strings
Trying to write a generic module where you can pass in an array of strings to format another string based on environment being deployed to, but keep getting input string not incorrect format.
Question:
- Does the format function take an array?
- Does the input string have to have formatting?
Here is the actual scenario:
- Parameter File would contain the following:
"appConfigurationKey": "Some config key",
"appConfigurationValue": "https://{est.com/{0}",
"appConfigurationValueContentType": null,
"appConfigurationName": "app config name",
"appConfigurationResourceGroup": "app config resource group",
"appConfigurationValueEnvReplacements": {
"dev": [
"dev value"
],
"qa": [
"qa value"
],
"uat": [
"uat value"
],
"prd": [
"prd value"
]
}
@allowed([
''
'dev'
'qa'
'uat'
'prd'
])
@description('The environment in which the resource(s) will be deployed')
param environment string = ''
@description('The region prefix or suffix for the resource name, if applicable.')
param region string = ''
@description('The name of the app configuration')
param appConfigurationName string
@description('The name of the Key Vaule')
param appConfigurationKey string
@secure()
@description('The value of the App configuration to create or update')
param appConfigurationValue string
@description('Labels to append to App Configuration Key')
param appConfigurationLabels array = []
@description('The content type of the configuration value')
param appConfigurationContentType string = ''
@description('')
param appConfigurationValueEnvReplacements object = {}
// if empty then yes (env agnostic config value) or
var appConfigReplacements = !empty(appConfigurationValueEnvReplacements) ? appConfigurationValueEnvReplacements : {
dev: []
qa: []
uat: []
prd: []
}
var appConfig = environment == 'dev' ? {
value: format(appConfigurationValue, appConfigReplacements.dev)
} : environment == 'qa' ? {
value: format(appConfigurationValue, appConfigReplacements.qa)
} : environment == 'uat' ? {
value: format(appConfigurationValue, appConfigReplacements.uat)
} : environment == 'prd' ? {
value: format(appConfigurationValue, appConfigReplacements.dev)
} : {
value: appConfigurationValue
}
resource azAppConfigurationKeyValuesDeployment 'Microsoft.AppConfiguration/configurationStores/keyValues@2022-05-01' = if (empty(appConfigurationLabels) || contains(appConfigurationLabels, 'default')) {
name: replace(replace('${appConfigurationName}/${appConfigurationKey}', '@environment', environment), '@region', region)
properties: {
value: replace(replace(appConfig.value, '@environment', environment), '@region', region)
contentType: empty(appConfigurationContentType) ? json('null') : appConfigurationContentType
}
}
// Deploys the same configuration value with different labels
resource azAppConfigurationKeyValuesWithLabelsDeployment 'Microsoft.AppConfiguration/configurationStores/keyValues@2022-05-01' = [for label in appConfigurationLabels: if (label != 'default' && !empty(appConfigurationLabels)) {
name: replace(replace('${appConfigurationName}/${appConfigurationKey}$${label}', '@environment', environment), '@region', region)
properties: {
value: replace(replace(appConfig.value, '@environment', environment), '@region', region)
contentType: empty(appConfigurationContentType) ? json('null') : appConfigurationContentType
}
}]
After some testing I realized array of string is not supported. Is there a way to make this current issue into a request for enhancement?
I believe this would need special syntax to implement in a backwards-compatible way. The format function does support passing an array as an argument, but the longstanding behavior of the ARM runtime is to convert the array to a string before injecting it into the format string as a single element. E.g.,
output foo string = format('{0}', ['fizz', 'buzz', 'pop'])
would compile to:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.9.1.41621",
"templateHash": "8261008250483932764"
}
},
"resources": [],
"outputs": {
"foo": {
"type": "string",
"value": "[format('{0}', createArray('fizz', 'buzz', 'pop'))]"
}
}
}
which, when deployed, would produce the following outputs:

In order to implement something close to the feature described, I think ARM would need an equivalent of JavaScript's function.prototype.apply() or PHP's call_user_func_array(), which would allow users to invoke a function by name with an array of arguments. For example, format('{0}', 'foo') might be equivalent to (and this is purely strawman syntax) apply('format', createArray('{0}', 'foo')) in ARM JSON or format.apply(['{0}', 'foo']) in Bicep.