Confronto tra JSON e Bicep per i modelli

Questo articolo confronta la sintassi Bicep con la sintassi JSON per i modelli di Azure Resource Manager (modelli ARM). Nella maggior parte dei casi, Bicep fornisce una sintassi meno dettagliata rispetto all'equivalente in JSON.

Se si ha familiarità con l'uso di JSON per sviluppare modelli ARM, usare gli esempi seguenti per ottenere informazioni sulla sintassi equivalente per Bicep.

Confrontare i file completi

Bicep Playground consente di visualizzare Bicep e JSON equivalente affiancati. È possibile confrontare le implementazioni della stessa infrastruttura.

Ad esempio, è possibile visualizzare il file per distribuire un SQL Server e un database. Bicep è circa la metà delle dimensioni del modello di Resource Manager.

Screenshot of side by side templates

Espressioni

Per creare un'espressione:

func()
"[func()]"

Parametri

Per dichiarare un parametro con un valore predefinito:

param orgName string = 'Contoso'
"parameters": {
  "orgName": {
    "type": "string",
    "defaultValue": "Contoso"
  }
}

Per ottenere un valore di parametro, usare il nome definito:

name: orgName
"name": "[parameters('orgName')]"

Variabili

Per dichiarare una variabile:

var description = 'example value'
"variables": {
  "description": "example value"
}

Per ottenere un valore di variabile, usare il nome definito:

workloadSetting: description
"workloadSetting": "[variables('description')]"

Stringhe

Per concatenare stringhe:

name: '${namePrefix}-vm'
"name": "[concat(parameters('namePrefix'), '-vm')]"

Operatori logici

Per restituire l'AND logico:

isMonday && isNovember
[and(parameter('isMonday'), parameter('isNovember'))]

Per impostare in modo condizionale un valore:

isMonday ? 'valueIfTrue' : 'valueIfFalse'
[if(parameters('isMonday'), 'valueIfTrue', 'valueIfFalse')]

Ambito di distribuzione

Per impostare l'ambito di destinazione della distribuzione:

targetScope = 'subscription'
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#"

Risorse

Per dichiarare una risorsa:

resource virtualMachine 'Microsoft.Compute/virtualMachines@2024-03-01' = {
  ...
}
"resources": [
  {
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2024-03-01",
    ...
  }
]

Distribuire una risorsa in modo condizionale:

resource virtualMachine 'Microsoft.Compute/virtualMachines@2024-03-01' = if(deployVM) {
  ...
}
"resources": [
  {
    "condition": "[parameters('deployVM')]",
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2024-03-01",
    ...
  }
]

Per impostare una proprietà della risorsa:

sku: '2016-Datacenter'
"sku": "2016-Datacenter",

Per ottenere l'ID risorsa di una risorsa nel modello:

nic1.id
[resourceId('Microsoft.Network/networkInterfaces', variables('nic1Name'))]

Cicli

Per scorrere gli elementi in una matrice o in un conteggio:

[for storageName in storageAccountNames: {
  ...
}]
"copy": {
  "name": "storagecopy",
  "count": "[length(parameters('storageAccountNames'))]"
},
...

Dipendenze delle risorse

Per Bicep è possibile impostare una dipendenza esplicita, ma questo approccio non è consigliato. In alternativa, fare affidamento sulle dipendenze implicite. Una dipendenza implicita viene creata quando una dichiarazione di risorsa fa riferimento all'identificatore di un'altra risorsa.

Di seguito viene illustrata un'interfaccia di rete con una dipendenza implicita da un gruppo di sicurezza di rete. Fa riferimento al gruppo di sicurezza di rete con netSecurityGroup.id.

resource netSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-11-01' = {
  ...
}

resource nic1 'Microsoft.Network/networkInterfaces@2023-11-01' = {
  name: nic1Name
  location: location
  properties: {
    ...
    networkSecurityGroup: {
      id: netSecurityGroup.id
    }
  }
}

Se è necessario impostare una dipendenza esplicita, usare:

dependsOn: [ storageAccount ]
"dependsOn": ["[resourceId('Microsoft.Storage/storageAccounts', 'parameters('storageAccountName'))]"]

Risorse di riferimento

Per ottenere una proprietà da una risorsa nel modello:

storageAccount.properties.primaryEndpoints.blob
[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob]

Per ottenere una proprietà da una risorsa esistente non distribuita nel modello:

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' existing = {
  name: storageAccountName
}

// use later in template as often as needed
storageAccount.properties.primaryEndpoints.blob
// required every time the property is needed
"[reference(resourceId('Microsoft.Storage/storageAccounts/', parameters('storageAccountName')), '2019-06-01').primaryEndpoints.blob]"

In Bicep usare la funzione di accesso annidata (::) per ottenere una proprietà in una risorsa annidata all'interno di una risorsa padre:

VNet1::Subnet1.properties.addressPrefix

Per JSON, usare la funzione di riferimento:

[reference(resourceId('Microsoft.Network/virtualNetworks/subnets', variables('subnetName'))).properties.addressPrefix]

Output

Per restituire una proprietà da una risorsa nel modello:

output hostname string = publicIP.properties.dnsSettings.fqdn
"outputs": {
  "hostname": {
    "type": "string",
    "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).dnsSettings.fqdn]"
  },
}

Per restituire in modo condizionale un valore:

output hostname string = condition ? publicIP.properties.dnsSettings.fqdn : ''
"outputs": {
  "hostname": {
    "condition": "[variables('condition')]",
    "type": "string",
    "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).dnsSettings.fqdn]"
  }
}

L'operatore ternario Bicep è l'equivalente alla funzione if in un file JSON del modello ARM, non alla proprietà condizione. La sintassi ternaria deve restituire un valore o l'altro. Se la condizione è false negli esempi precedenti, Bicep restituisce un nome host con una stringa vuota, ma JSON non restituisce valori.

Riutilizzo del codice

Per separare una soluzione in più file:

Passaggi successivi