Home > Net >  Powershell - Get value from JSON using string from array [duplicate]
Powershell - Get value from JSON using string from array [duplicate]

Time:09-29

What im 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

CodePudding user response:

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 .}} 
}
  • Related