arraysjsonpowershell

Json with Array Data parsing in Powershell


Sharing below sample Data $vmStats and $VM_List is a variable with list of white-space separated VM names.

Sample Json Data

{
    "totalRecords": 4,
    "pageNo": 0,
    "errorMessage": "",
    "errorCode": 0,
    "vmDeployStatusList": [
        {
            "vmStatus": 1,
            "slaStatus": 1,
            "vmUsedSpace": 23451098,
            "name": "TEST-SRV11",
            "psClient": "@{hostName=cluster1.local.com; clientId=110; clientName=cluster1.local.com; status=1; flags=1}",
            "dcPlan": ""
        },
        {
            "vmStatus": 1,
            "slaStatus": 1,
            "vmUsedSpace": 8248576001,
            "name": "TEST-SRV10",
            "psClient": "@{hostName=cluster1.local.com; clientId=40; clientName=cluster1.local.com; status=0; flags=1}",
            "dcPlan": ""
        },
        {
            "vmStatus": 2,
            "slaStatus": 1,
            "vmUsedSpace": 76131082098,
            "name": "TEST-SRV21",
            "psClient": "@{hostName=cluster1.local.com; clientId=24; clientName=cluster1.local.com; status=1; flags=1}",
            "dcPlan": ""
        },
        {
            "vmStatus": 2,
            "slaStatus": 1,
            "vmUsedSpace": 5540098763,
            "name": "TEST-SRV23",
            "psClient": "@{hostName=cluster1.local.com; clientId=11; clientName=cluster1.local.com; status=3; flags=1}",
            "dcPlan": ""
        }
    ]
}

I want to extract two values from the above Json data, vmStatus and status (part of psClient).

I tried different iterations of the below code, but I couldn't get the second value status.

Code

$VM_Stats_Col = @()
foreach ($VM in $VM_List) {
    $VM_Stats = Get-Content -Path $vmStats |
        ConvertFrom-Json |
        Select-Object -ExpandProperty vmDeployStatusList |
        Where-Object { $_.name -eq $VM } |
        Select-Object -Property name,
            @{N='VM_Status'; E={$_.vmStatus}},
            @{N='VM_Dep_Stats'; E={ 
                $psClientObj = ($_ | Select-Object -ExpandProperty psClient) -replace '@{', '{' -replace '}', '}'
                $psClientObj = $psClientObj | ConvertFrom-Json
                $psClientObj.status
            }}

    $VM_Stats_Col += $VM_Stats
}

Write-Output $VM_Stats_Col

The $_.psClient returns the full list of values under that Property. So is it good option to extract the value of status by using some regex on that ?


Solution

  • $VM_Stats_Col = @()
    $JsonData = Get-Content -Path $vmStats | ConvertFrom-Json
    
    foreach ($VM in $VM_List) {
        $VM_Data = $JsonData.vmDeployStatusList | Where-Object { $_.name -eq $VM }
    
        if ($VM_Data) {
            # Clean up the hashtable-like string and parse it manually
            $psClientRaw = $VM_Data.psClient -replace '^@{', '' -replace '}$', ''
            $psClientDict = @{}
    
            # Split by semicolon and extract key=value pairs
            $psClientRaw -split '; ' | ForEach-Object {
                $pair = $_ -split '=', 2
                if ($pair.Length -eq 2) {
                    $psClientDict[$pair[0].Trim()] = $pair[1].Trim()
                }
            }
    
            # Build output object
            $VM_Stats = [PSCustomObject]@{
                Name            = $VM_Data.name
                VM_Status       = $VM_Data.vmStatus
                VM_ClientStatus = $psClientDict['status']
            }
    
            $VM_Stats_Col += $VM_Stats
        }
    }
    
    Write-Output $VM_Stats_Col
    
    1. psClient is not valid JSON — it looks like a PowerShell hashtable string.

    2. We clean the string by removing @{ and } and then split it by ; to get key-value pairs.

    3. Those pairs are added to a dictionary ($psClientDict), and we access the status value from it.

    4. The output is a list of custom objects with Name, VM_Status, and VM_ClientStatus.
      Name VM_Status VM_ClientStatus

      ---- --------- ---------------

      TEST-SRV11 1 1

      TEST-SRV10 1 0

      TEST-SRV21 2 1

      TEST-SRV23 2 3