HunkyDory
HunkyDory

Reputation: 11

Adding a Property to JSON with Powershell

can someone please tell me what I am doing wrong here? I am trying to add additional properties to an existing JSON file.

This is my existing JSON File:

{
  "filePath": "F:\\Program Files (x86)\\Common Files\\XXXX\\Services\\file.exe",
  "Services": {
    "BBBBBB": {
      "Id": "BBBBBB",
      "Installed": true,
      "OverrideValues": {}
    },
    "XXXX1Service": {
      "Id": "XXXX1Service",
      "Installed": true,
      "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    },
    "XXXX2Service": {
      "Id": "XXXX2Service",
      "Installed": true,
      "OverrideValues": {
        "Application Tier URL": {
          "Value": "my.com"
        },
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    },
    "XXXX3Service": {
      "Id": "XXXX3Service",
      "Installed": true,
      "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    },
    "XXXX4Service": {
      "Id": "XXXX4Service",
      "Installed": true,
      "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    }
  }
}

I am trying to insert properties to make it look like this (look under XXX3Service):

{
  "filePath": "F:\\Program Files (x86)\\Common Files\\XXXX\\Services\\file.exe",
  "Services": {
    "BBBBBB": {
      "Id": "BBBBBB",
      "Installed": true,
      "OverrideValues": {}
    },
    "XXXX1Service": {
      "Id": "XXXX1Service",
      "Installed": true,
      "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    },
    "XXXX2Service": {
      "Id": "XXXX2Service",
      "Installed": true,
      "OverrideValues": {
        "Application Tier URL": {
          "Value": "my.com"
        },
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    },
    "XXXX3Service": {
      "Id": "XXXX3Service",
      "Installed": true,
      "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        },
        "XXX 3 Service": {
          "Enabled": true
        },
        "My Token": {
          "Value": "1234567890"
        },
        "Authority": {
          "Value": "authority.com"
        },
        "ThisSecret": {
          "Value": "1234-1234-1234-1234"
        }
      }
    },
    "XXXX4Service": {
      "Id": "XXXX4Service",
      "Installed": true,
      "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        }
      }
    }
  }
}

My Code looks like this:

# Get json content from a file
$json = Get-Content .\source.json

# convert the json to be a powershell object
$psObject = $json | ConvertFrom-Json

# useful for referencing to see all of the properties
# $psObject.Services | Select-Object *
# $psObject.Services.XXXX3Service
# $psObject.Services.XXXX3Service.OverrideValues

#* ConvertTo-Json the max allowed depth is 100
$newProperty = @"
{
    "OverrideValues": {
        "HostName": {
          "Enabled": true,
          "Value": "my.com"
        },
        "XXX 3 Service": {
          "Enabled": true
        },
        "My Token": {
          "Value": "1234567890"
        },
        "Authority": {
          "Value": "authority.com"
        },
        "ThisSecret": {
          "Value": "1234-1234-1234-1234"
        }
      }
}
"@ | ConvertFrom-Json -Depth 100

# get the name to overwrite the existing property so it's not nested
$propName = $newProperty.PSObject.Properties | Select-Object -Expand Name

# here we supply the $propname value in json as well as use the value(s) under the $newProperty to overwrite the existing property
$psObject.Services.XXXX3Service | Add-Member -MemberType NoteProperty -Name $propName -Value $newProperty.$propName -Force

# lastly convert and export the json
$psObject | ConvertTo-Json -Depth 100 | Out-File "C:\temp\good.json"

however I am getting the following errors:

ConvertFrom-Json : A parameter cannot be found that matches parameter name 'Depth'.
At C:\Users\user\Downloads\json.ps1:38 char:23
+ "@ | ConvertFrom-Json -Depth 100
+                       ~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [ConvertFrom-Json], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

Add-Member : Cannot bind argument to parameter 'Name' because it is null.
At C:\Users\user\Downloads\json.ps1:44 char:77
+ ... Service | Add-Member -MemberType NoteProperty -Name $propName -Value  ...
+                                                         ~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Add-Member], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddMemberCo
   mmand

Upvotes: 1

Views: 1546

Answers (1)

mklement0
mklement0

Reputation: 440162

tl;dr

  • Remove -Depth 100 from your ConvertFrom-Json call.
  • With ConvertFrom-Json, use of -Depth is generally not needed, and in Windows PowerShell that parameter doesn't even exist (whereas it does for the complementary cmdlet, ConvertTo-Json, where it is often needed).

  • As Cpt.Whale points out, in Windows PowerShell the ConvertFrom-Json - note the From - does not have a -Depth parameter. It exists in PowerShell (Core) 7+, where, however, it is rarely needed.

    • Despite the parameter having the same name as ConvertTo-Json's (see below), it functions very differently: It is used to enforce that the input JSON isn't more deeply nested than the given -Depth value, and reports an error if it is.
    • As zett42 points out, the default value is 1024, so only more deeply nested JSON would cause an error - which seems unlikely. However, you can use -Depth to increase that limit, up to 2,147,483,647 ([int]::MaxValue), at least formally.
  • By contrast, ConvertTo-Json - note the To - does have this parameter in Windows PowerShell too, and, unfortunately, it is frequently needed:

    • By default, PowerShell limits the serialization depth to two levels of recursion, necessitating an explicit -Depth argument to properly serialize more deeply nested object graphs - see this post. Absent that, if the default serialization depth is exceeded, quiet truncation occurs in Windows PowerShell, whereas in PowerShell (Core) you now at least get a warning.

Upvotes: 2

Related Questions