1

What I'm trying to do is getting one specific value from nested JSON. Using array keys as expression.

Array with keys and values:

 $AccountService = @{
    'root.branch.setting1'= 'Val1'
    'root.branch.setting2'= 'Val2'
    'root.branch.setting3'= 'Val3'
}

Create JSON Object

$json = Get-Content 'C:\Users\ramosfer\Documents\test.json' | ConvertFrom-Json

Get every key from array using a loop to get the value from the JSON. Expecting something like this in the Expression ($json.root.branch.setting1)

$AccountService.GetEnumerator() | % { 
    $json | Select-Object @{Name="Val"; Expression={$json.$_}}
}

Use this $json.$_ and expect something like this

Val                                                                                                                                                                                           
---
Val1
Val2
Val3
2
  • 1
    Have you considered Invoke-Expression "`$json.$_" Commented Sep 28, 2021 at 21:23
  • Im kinda new for PS. Could u please help me being more specific. Thanks! Commented Sep 28, 2021 at 21:32

1 Answer 1

1

The best way of resolving nested properties is to resolve them one at a time :)

A simpler example, for retrieving just one value:

$json = '{"root":{"branch":{"setting1":"Value 1","setting2":"Value 2","setting3":"Value 3"}}}' |ConvertFrom-Json

# define the "path" to the value we want
$path = 'root.branch.setting1'

# split path into individual property names
$path = $path.Split('.')

# start from the root object and then start "walking" down the object hierarchy
$cursor = $json
foreach($property in $path)
{
  # advance cursor one level deeper
  $cursor = $cursor.$property
}

# this will now contain "Value 1"
$cursor

You can turn this into a neat little function:

function Resolve-MemberChain 
{
  param(
    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
    [psobject[]]$InputObject,

    [Parameter(Mandatory = $true, Position = 0)]
    [string[]]$MemberPath,

    [Parameter(Mandatory = $false)]
    [string]$Delimiter
  )

  begin {
    if($PSBoundParameters.ContainsKey('Delimiter')){
      $MemberPath = $MemberPath.Split([string[]]@($Delimiter))
    }
  }

  process {
    foreach($obj in $InputObject){
      $cursor = $obj
      foreach($member in $MemberPath){
        $cursor = $cursor.$member
      }
    
      $cursor
    }
  }
}

Then use it like this:

$json |Resolve-MemberChain 'root.branch.setting1' -Delimiter '.'

Or, as in your case, within a calculated property expression, like so:

$AccountService.GetEnumerator()|%{
  $path = $_.Key
  $json |Select @{Name='Val';Expression={$_ |Resolve-MemberChain $path -Delimiter .}} 
}
Sign up to request clarification or add additional context in comments.

1 Comment

This one solve the issue and gives the result. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.