Welcome Forums General PowerShell Q&A How to add element to object

Viewing 9 reply threads
  • Author
    Posts
    • #166223
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      I have this use case of manipulating Azure object JSON templates.
      Take this example https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-site-to-site-vpn/azuredeploy.parameters.json which looks like

      {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
          "adminUsername": {
            "value": "GEN-UNIQUE"
          },
          "localGatewayIpAddress": {
            "value": "52.25.48.88"
          },
          "localAddressPrefix": {
            "value": "10.0.0.0/24"
          },
          "azureVNetAddressPrefix": {
            "value": "10.3.0.0/16"
          },
          "subnetPrefix": {
            "value": "10.3.0.0/24"
          },
          "gatewaySubnetPrefix": {
            "value": "10.3.200.0/29"
          },
          "sharedKey": {
            "value": "GEN-UNIQUE"
          },
          "adminPasswordOrKey": {
            "value": "GEN-SSH-PUB-KEY"
          }
        }
      }
      

      Now I can read it fine like this:

      $Uri = 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-site-to-site-vpn/azuredeploy.parameters.json'
      $myParamterSet = Invoke-WebRequest $Uri | ConvertFrom-Json
      

      and we can see the parameters like

      $myParamterSet.parameters
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      

      We can even change them like

      PS C:\scripts> $myParamterSet.parameters.adminUsername.value = 'bla1'
      
      PS C:\scripts> $myParamterSet.parameters
      
      adminUsername          : @{value=bla1}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      

      My question is how to add another parameter to this parameter set?
      For example, I want to add

      environment     : @{value=dev}
      

      Trying to add an element fails:

      PS C:\scripts> $myParamterSet.parameters += [PSCustomObject]@{environment='dev'}
      Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'.
      At line:1 char:1
      + $myParamterSet.parameters += [PSCustomObject]@{environment='dev'}
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidOperation: (op_Addition:String) [], RuntimeException
          + FullyQualifiedErrorId : MethodNotFound
      

      Get-Member shows that these parameters are PS Custom Objects:

      PS C:\scripts> $myParamterSet.parameters | Get-Member
      
      
         TypeName: System.Management.Automation.PSCustomObject
      
      Name                   MemberType   Definition                                                                             
      ----                   ----------   ----------                                                                             
      Equals                 Method       bool Equals(System.Object obj)                                                         
      GetHashCode            Method       int GetHashCode()                                                                      
      GetType                Method       type GetType()                                                                         
      ToString               Method       string ToString()                                                                      
      adminPasswordOrKey     NoteProperty System.Management.Automation.PSCustomObject adminPasswordOrKey=@{value=GEN-SSH-PUB-KEY}
      adminUsername          NoteProperty System.Management.Automation.PSCustomObject adminUsername=@{value=bla1}                
      azureVNetAddressPrefix NoteProperty System.Management.Automation.PSCustomObject azureVNetAddressPrefix=@{value=10.3.0.0/16}
      gatewaySubnetPrefix    NoteProperty System.Management.Automation.PSCustomObject gatewaySubnetPrefix=@{value=10.3.200.0/29} 
      localAddressPrefix     NoteProperty System.Management.Automation.PSCustomObject localAddressPrefix=@{value=10.0.0.0/24}    
      localGatewayIpAddress  NoteProperty System.Management.Automation.PSCustomObject localGatewayIpAddress=@{value=52.25.48.88} 
      sharedKey              NoteProperty System.Management.Automation.PSCustomObject sharedKey=@{value=GEN-UNIQUE}              
      subnetPrefix           NoteProperty System.Management.Automation.PSCustomObject subnetPrefix=@{value=10.3.0.0/24}   
      

      How do I add one more?

    • #166226
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      nvm, this works:

      $myParamterSet.parameters | Add-Member -MemberType NoteProperty -Name 'Environmnmet' -Value ([PSCustomObject]@{value='dev'})
      
    • #166244
      Participant
      Topics: 2
      Replies: 512
      Points: 1,309
      Helping Hand
      Rank: Community Hero

      You can also do:

      $myParameterSet.parameters = $myParameterSet.Parameters | Select-Object -Property @{ Name= 'Environmnmet'; Expression = {[PSCustomObject]@{value='dev'}} }

       

    • #166271
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      @Joel nice!
      Now I’m stuck at trying to add a child object.

      For example how do I add a node like:

              "ApplicationName": {
                  "type": "string",
                  "maxLength": 3,
                  "metadata": {
                      "description": "some desc"
                  }
              }
      

      where the resulting PS object looks like:

      $myParameterSet.parameters.ApplicationName
      
      type   maxLength metadata                
      ----   --------- --------                
      string         3 @{description=some desc}
      
    • #166483
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      @Joel,
      Actually, using Select does not work:

      $Uri = 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-site-to-site-vpn/azuredeploy.parameters.json'
      $myParameterSet = Invoke-WebRequest $Uri | ConvertFrom-Json
      $myParameterSet.parameters
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      
      $myParameterSet.parameters = $myParameterSet.Parameters | 
          Select-Object -Property @{ Name= 'add1'; Expression = {[PSCustomObject]@{value='dev1'}} }
      
      $myParameterSet.parameters
      
      add1         
      ----         
      @{value=dev1}
      
      
    • #166489
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      Whereas Add-Member works:

      $Uri = 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-site-to-site-vpn/azuredeploy.parameters.json'
      $myParameterSet = Invoke-WebRequest $Uri | ConvertFrom-Json
      $myParameterSet.parameters
      $myParameterSet.parameters | Add-Member -MemberType NoteProperty -Name 'Environmnmet' -Value ([PSCustomObject]@{value='dev'})
      $myParameterSet.parameters
      
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      Environmnmet           : @{value=dev}
      
    • #166495
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      I think I got it:

      $Uri = 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-site-to-site-vpn/azuredeploy.parameters.json'
      $myParameterSet = Invoke-WebRequest $Uri | ConvertFrom-Json
      $myParameterSet.parameters
      $myParameterSet.parameters | Add-Member -MemberType NoteProperty -Name 'ApplicationName' -Value ([PSCustomObject]@{})
      $myParameterSet.parameters
      $myParameterSet.parameters.ApplicationName | Add-Member -MemberType NoteProperty -Name 'type' -Value 'string'
      $myParameterSet.parameters.ApplicationName | Add-Member -MemberType NoteProperty -Name 'maxlength' -Value 3
      $myParameterSet.parameters.ApplicationName | Add-Member -MemberType NoteProperty -Name 'metadata' -Value ([PSCustomObject]@{description = 'my desc'})
      $myParameterSet.parameters
      $myParameterSet.parameters.ApplicationName
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      ApplicationName        : 
      
      adminUsername          : @{value=GEN-UNIQUE}
      localGatewayIpAddress  : @{value=52.25.48.88}
      localAddressPrefix     : @{value=10.0.0.0/24}
      azureVNetAddressPrefix : @{value=10.3.0.0/16}
      subnetPrefix           : @{value=10.3.0.0/24}
      gatewaySubnetPrefix    : @{value=10.3.200.0/29}
      sharedKey              : @{value=GEN-UNIQUE}
      adminPasswordOrKey     : @{value=GEN-SSH-PUB-KEY}
      ApplicationName        : @{type=string; maxlength=3; metadata=}
      
      type      : string
      maxlength : 3
      metadata  : @{description=my desc}
      

      The trick to creating a subnode is line 4 creating an empty PSCustomObject, otherwise line 6 fails

    • #166501
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      and when you spit it back out to JSON, it looks right (which is the whole point behind this exercise)

      $myParameterSet | ConvertTo-Json | Out-File .\test1.txt 
      notepad .\test1.txt
      
      {
          "$schema":  "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
          "contentVersion":  "1.0.0.0",
          "parameters":  {
                             "adminUsername":  {
                                                   "value":  "GEN-UNIQUE"
                                               },
                             "localGatewayIpAddress":  {
                                                           "value":  "52.25.48.88"
                                                       },
                             "localAddressPrefix":  {
                                                        "value":  "10.0.0.0/24"
                                                    },
                             "azureVNetAddressPrefix":  {
                                                            "value":  "10.3.0.0/16"
                                                        },
                             "subnetPrefix":  {
                                                  "value":  "10.3.0.0/24"
                                              },
                             "gatewaySubnetPrefix":  {
                                                         "value":  "10.3.200.0/29"
                                                     },
                             "sharedKey":  {
                                               "value":  "GEN-UNIQUE"
                                           },
                             "adminPasswordOrKey":  {
                                                        "value":  "GEN-SSH-PUB-KEY"
                                                    },
                             "ApplicationName":  {
                                                     "type":  "string",
                                                     "maxlength":  3,
                                                     "metadata":  "@{description=my desc}"
                                                 }
                         }
      }
      
    • #166537
      Participant
      Topics: 9
      Replies: 430
      Points: 729
      Helping Hand
      Rank: Major Contributor

      This is actually a bug in ConvertTo-Json version 3.1.0.0 out of the C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.Utility\v4.0_3.0.0.0__31bf3856ad364e35\Microsoft.PowerShell.Commands.Utility.dll

      Proof:

      @'
      {
          "$schema": "https://schema.management.azure.com/schemas/2018-05-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
              "ApplicationName": {
                  "type": "string",
                  "maxLength": 3,
                  "metadata": {
                      "description": "my desc"
                  }
              },
              "plan_name": {
                  "type": "String"
              }
          },
          "variables": {
              "resourceNames": {
                  "name": "EDSENDGRID06",
                  "commonResourceGroup": "[tolower(concat(parameters('ApplicationName'),'-',parameters('Environment'),'-',parameters('shortlocation'),'-',parameters('tenant'),'-rgp-','01'))]"
              },
              "TemplateURLs": {
                  "sendgrid": "[concat(parameters('artifacts_baseUri'),'/ArmTemplates/master/Public/lib/linkedTemplates/sendgrid.json')]"
              }
          }
      }
      '@ | ConvertFrom-Json | ConvertTo-Json
      

      This retuns:

      {
          "$schema":  "https://schema.management.azure.com/schemas/2018-05-01/deploymentTemplate.json#",
          "contentVersion":  "1.0.0.0",
          "parameters":  {
                             "ApplicationName":  {
                                                     "type":  "string",
                                                     "maxLength":  3,
                                                     "metadata":  "@{description=my desc}"
                                                 },
                             "plan_name":  {
                                               "type":  "String"
                                           }
                         },
          "variables":  {
                            "resourceNames":  {
                                                  "name":  "EDSENDGRID06",
                                                  "commonResourceGroup":  "[tolower(concat(parameters(\u0027ApplicationName\u0027),\u0027-\u0027,parameters(\u0027Environ
      ment\u0027),\u0027-\u0027,parameters(\u0027shortlocation\u0027),\u0027-\u0027,parameters(\u0027tenant\u0027),\u0027-rgp-\u0027,\u002701\u0027))]"
                                              },
                            "TemplateURLs":  {
                                                 "sendgrid":  "[concat(parameters(\u0027artifacts_baseUri\u0027),\u0027/ArmTemplates/master/Public/lib/linkedTemplates/se
      ndgrid.json\u0027)]"
                                             }
                        }
      }
      

      Note the messed up line 8 in the output compared to what it should be – lines 9,10,11 in the input

      I wrote a Fix-Json function to fix this – part of the AZSBTools PS module:

      $TempFile = New-TemporaryFile
      @'
      {
          "$schema": "https://schema.management.azure.com/schemas/2018-05-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
              "ApplicationName": {
                  "type": "string",
                  "maxLength": 3,
                  "metadata": {
                      "description": "my desc"
                  }
              },
              "plan_name": {
                  "type": "String"
              }
          },
          "variables": {
              "resourceNames": {
                  "name": "EDSENDGRID06",
                  "commonResourceGroup": "[tolower(concat(parameters('ApplicationName'),'-',parameters('Environment'),'-',parameters('shortlocation'),'-',parameters('tenant'),'-rgp-','01'))]"
              },
              "TemplateURLs": {
                  "sendgrid": "[concat(parameters('artifacts_baseUri'),'/ArmTemplates/master/Public/lib/linkedTemplates/sendgrid.json')]"
              }
          }
      }
      '@ | ConvertFrom-Json | ConvertTo-Json | Out-File $TempFile 
      Fix-Json $TempFile 
      

      Now the output looks like:

      {
          "$schema":  "https://schema.management.azure.com/schemas/2018-05-01/deploymentTemplate.json#",
          "contentVersion":  "1.0.0.0",
          "parameters":  {
                             "ApplicationName":  {
                                                     "type":  "string",
                                                     "maxLength":  3,
                                                     "metadata":  {
                                                         "description": "my desc"
                                                     }
                                                 },
                             "plan_name":  {
                                               "type":  "String"
                                           }
                         },
          "variables":  {
                            "resourceNames":  {
                                                  "name":  "EDSENDGRID06",
                                                  "commonResourceGroup":  "[tolower(concat(parameters(\u0027ApplicationName\u0027),\u0027-\u0027,parameters(\u0027Environ
      ment\u0027),\u0027-\u0027,parameters(\u0027shortlocation\u0027),\u0027-\u0027,parameters(\u0027tenant\u0027),\u0027-rgp-\u0027,\u002701\u0027))]"
                                              },
                            "TemplateURLs":  {
                                                 "sendgrid":  "[concat(parameters(\u0027artifacts_baseUri\u0027),\u0027/ArmTemplates/master/Public/lib/linkedTemplates/se
      ndgrid.json\u0027)]"
                                             }
                        }
      }
      
    • #166552
      Participant
      Topics: 2
      Replies: 512
      Points: 1,309
      Helping Hand
      Rank: Community Hero

      Ah, if you wanted to keep existing properties, you’d need to do Select-Object -Property *, @{ <# rest of the thing I posted before #> }

Viewing 9 reply threads
  • The topic ‘How to add element to object’ is closed to new replies.