arraysjsonpowershellpsobject

Extracting value from nested object


I'm attempting to extract a particular value from a nested JSON response in PowerShell.

I am performing a GET method on a REST endpoint and getting the following back.

{
  "value": [
    {
      "id": 2370,
      "customFields": [
        "@{id=60; caption=M\u0026S Agreement Status ; type=Text; entryMethod=List; numberOfDecimals=0; value=Active}",
        "@{id=68; caption=Maintenance Renewal Notes; type=Text; entryMethod=EntryField; numberOfDecimals=0}",
        "@{id=81; caption=Reseller; type=Text; entryMethod=List; numberOfDecimals=0}",
        "@{id=105; caption=Product Type; type=Text; entryMethod=List; numberOfDecimals=0; value=GoAnywhere}"
      ]
    }
  ],
  "Count": 1
}

I am unsure of how to extract the "value" field which contains "GoAnywhere" from the final nested string.

I have tried this.

$agreementsResponse | ConvertFrom-Json | ForEach-Object{$_.value} | Select customFields

and it is getting me a single string in an Object:

customFields                                                                                                                                                                                                          
------------                                                                                                                                                                                                          
{@{id=60; caption=M&S Agreement Status ; type=Text; entryMethod=List; numberOfDecimals=0; value=Active}, @{id=68; caption=Maintenance Renewal Notes; type=Text; entryMethod=EntryField; numberOfDecimals=0}, @{id=8...

Solution

  • This is a really odd API response, what you have in the customFields Json array seem to be string representations of PowerShell's custom objects. I assume what you're looking to do is extract the line that has a value=GoAnywhere, perhaps a good approach can be to convert these strings into objects, then it will be easier to extract data from them. See ConvertFrom-StringData for details.

    Using the Json sample from question the code would be:

    $json = $agreementsResponse | ConvertFrom-Json
    $result = $json.value.customFields | ForEach-Object {
        $hash = $_ -replace '^@\{|\}$' -replace '\s*;\s*', "`n" |
            ConvertFrom-StringData
    
        if ($hash.ContainsKey('value') -and $hash['value'] -eq 'GoAnywhere') {
            $hash
        }
    }
    $result
    

    Then, in $result, for this specific example you'd get a single hashtable than you can easily manipulate / extract information from:

    Name                           Value
    ----                           -----
    id                             105
    value                          GoAnywhere
    entryMethod                    List
    type                           Text
    numberOfDecimals               0
    caption                        Product Type