1

I'm working with a script in PowerShell that updates JSON data, accessing an modifying data that's 3 layers deep. The general flow is:

$obj = Get-Content -Raw -Path $pathstring | ConvertFrom-Json
$obj.prop1.prop2.prop3.prop4 = "test"
$outjson = ConvertTo-Json -InputObject $obj -Depth 5
Set-Content -Path $pathstring -Value $outjson

This works when the property already exists. However, in some cases $obj.prop1.prop2.prop3.prop4 does not exist. I want to add a series of nested properties to a PowerShell object, and then convert that to JSON to create it.

Is that possible/how is that done/is there a better way to add JSON values to something in PowerShell?

Edit: I'm currently running

if(Get-Member -inputobject $js.prop1 -name "prop2" -Membertype Properties)

to test if the property exists, and if prop2 doesn't exist then I need to create all the properties.

3 Answers 3

3

@J.Peter I really liked your solution, but I needed to be able to provide a way to add properties in the name with periods. so I made a slight mod to yours. I added an escape character to the parameters, that gets replaced in the string with a period.

Edit: another rewrite. Got rid of the recursion, and now it can handle creating very complex objects as well as having "." in the property names. Was so happy with the changes I made a gist for it https://gist.github.com/tcartwright/72cac052e1f8058abed1f7028f674a10 with credits.

function Add-NoteProperty {
    param(
        $InputObject,
        $Property,
        $Value,
        [switch]$Force,
        [char]$escapeChar = '#'
    )
    process {
        $path = $Property -split "\."
        $obj = $InputObject
        # loop all but the very last property
        for ($x = 0; $x -lt $path.count -1; $x ++) {
            $propName = $path[$x] -replace $escapeChar, '.'
            if (!($obj | Get-Member -MemberType NoteProperty -Name $propName)) {
                $obj | Add-Member NoteProperty -Name $propName -Value (New-Object PSCustomObject) -Force:$Force.IsPresent
            }
            $obj = $obj.$propName
        }
        $propName = ($path | Select-Object -Last 1) -replace $escapeChar, '.'
        if (!($obj | Get-Member -MemberType NoteProperty -Name $propName)) {
            $obj | Add-Member NoteProperty -Name $propName -Value $Value -Force:$Force.IsPresent
        }
    }
}


$obj = [PSCustomObject]@{}

Add-NoteProperty -InputObject $obj -Property "Person.Name.First" -Value "Tim"
Add-NoteProperty -InputObject $obj -Property "Person.Name.Last" -Value "C"
Add-NoteProperty -InputObject $obj -Property "Person.Age" -Value "Old"
Add-NoteProperty -InputObject $obj -Property "Person.Address.City" -Value "Houston"
Add-NoteProperty -InputObject $obj -Property "Person.Address.State" -Value "Texas"
$obj | ConvertTo-JSON

Which results in:

{
    "Person":  {
                   "Name":  {
                                "First":  "Tim",
                                "Last":  "C"
                            },
                   "Age":  "Old",
                   "Address":  {
                                   "City":  "Houston",
                                   "State":  "Texas"
                               }
               }
}
Sign up to request clarification or add additional context in comments.

3 Comments

made more slight edits to the script, but I am only updating the GIST from here on out.
@J.Peter, I made a repo for this module, and and a powershell module. Let me know your github user name and I will make you a contributor. github.com/tcartwright/AddNoteProperty powershellgallery.com/packages/AddNoteProperty/1.0.1
Wow its been a while. Nice to see you found use of it. Think i might have some improvements. Going to submit a pull request on the repo when i have some time. My github would be github.com/sipho102
1

If a property doesn't exist you need to add it, otherwise you can't assign a value to it:

$obj.prop1.prop2.prop3 | Add-Member -Type NoteProperty -Name 'prop4' -Value 'test'

7 Comments

What about if prop1, prop2, and prop3 also don't exist in some files
You need to add them first, obviously.
What do I put for -Value for $obj, prop1, prop2, prop3? I don't want to have useless text in the json, just a clean nested value.
No, you need recursion if you want to create a substructure of arbitrary depth. You can check for the presence of a property like this: $obj.prop1.PSObject.Properties['prop2'].IsInstance.
I edited the question to give you more detail. I only need to check if one thing exists, and then create the 3 additional layers if it doesn't
|
1

I recently encountered a similiar problem where I needed to add nested properties to objects so I wrote a recursive function for it.

function Add-NoteProperty {
    param(
        $InputObject,
        $Property,
        $Value,
        [switch]$Force
    )
    process {
        [array]$path = $Property -split "\."
        If ($Path.Count -gt 1) {
            #go in to recursive mode
            $Obj = New-Object PSCustomObject
            Add-NoteProperty -InputObject $Obj -Property ($path[1..($path.count - 1)] -join ".") -Value $Value
        }
        else {
            #last node
            $Obj = $Value
        }
        $InputObject | Add-Member NoteProperty -Name $path[0] -Value $Obj -Force:$Force
    }
}

Usage example:

$obj = [PSCustomObject]@{
    prop1 = "1"
    prop2 = "2"
}
Add-NoteProperty -InputObject $obj -Property "prop3.nestedprop31.nestedprop311" -Value "somevalue"
$obj | ConvertTo-JSON
<#Should give you this 
{
    "prop1":  "1",
    "prop2":  "2",
    "prop3":  {
                  "subprop":  {
                                  "asdf":  "3"
                              }
              }
}
#>

2 Comments

Sigh. This should be in the language.
I really liked your solution till i tried to add two properties to the same nested object... Need to think that over...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.