Michael B
Michael B

Reputation: 12228

Accessing an pscustomobject with dot notation in a string

Given this piece of code

$Object = @"
{
    "Item1":{
        "Subitem1":{
            "Subsubvalue":"Value"
        }
    },
    "Value1":"value1"
}

"@ | ConvertFrom-Json 

and given the following string (that I don't know at runtime, I've just got a string with an object path)

$String = "$Object.Item1.Subitem1.Subsubvalue"

I am trying to do the following - but I can't find a way to make it work

PS C:\> $Substring = $string.substring(8)
PS C:\> $Object.$Substring 
Value 

My ultimate goal is to get to modify the contents of that

PS C:\> $Object.$Substring = "something else" 

Obviously $substring approach doesn't work, nor the other approaches I've tried.

Upvotes: 0

Views: 706

Answers (3)

Negatar
Negatar

Reputation: 809

You might also consider using a dedicated function to do this work rather than depending on Invoke-Expression. Solutions like this are detailed in this tread.

Upvotes: 0

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200233

Invoke-Expression is no better than eval in other languages. It's far too likely to do something undesired/unexpected because it evaluates the given string as code. I would not recommend going that route unless you know exactly what you're doing.

Try a recursive function instead:

function Get-NestedItem {
    Param(
        [Parameter(Mandatory=$true, Position=0)]
        $InputObject,

        [Parameter(Mandatory=$false, Position=1)]
        [AllowEmptyString()]
        [string]$Path = '',

        [Parameter(Mandatory=$false, Position=2)]
        [string]$Delimiter = '.'
    )

    if ($Path) {
        $child, $rest = $Path.Split($Delimiter, 2)
        Get-NestedItem $InputObject.$child $rest
    } else {
        $InputObject
    }
}

$Object = ...
$Path   = 'Item1.Subitem1.Subsubvalue'

Get-NestedItem $Object $Path

Upvotes: 1

Chris Gardner
Chris Gardner

Reputation: 71

You can use Invoke-expression to handle this as it will parse the string passed to it as if it was a command.

So you can do the following:

Invoke-Expression -Command "$string"

This will return:

Value

So you can then do:

Invoke-Expression -Command "$String = `"Something else`""

Which will set the value to "Something else".

Upvotes: 2

Related Questions