Accessing unknown levels of PSCustomObject nested object

171 Views Asked by At

I'm getting a response from an API with unknown nested levels of properties, this is an example:

affects_rating          : True
assets                  : {@{asset=xxxxxxxxxxxxx; identifier=; category=low; importance=0.0; is_ip=True}}
details                 : @{check_pass=; diligence_annotations=; geo_ip_location=NL; grade=GOOD; remediations=System.Object[]; vulnerabilities=System.Object[]; dest_port=443; rollup_end_date=2021-06-06; 
                          rollup_start_date=2020-03-18}
evidence_key            : xxxxxxxxx:xxxx
first_seen              : 2020-03-18
last_seen               : 2021-06-06
related_findings        : {}
risk_category           : Diligence
risk_vector             : open_ports
risk_vector_label       : Open Ports
rolledup_observation_id : xxxx-xxxx==
severity                : 1.0
severity_category       : minor
tags                    : {}
asset_overrides         : {}
duration                : 
comments                : 
remaining_decay         : 59

temporary_id            : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
affects_rating          : True
assets                  : {@{asset=xxxx.xxxx.com; identifier=; category=low; importance=0.0002340946; is_ip=False}, @{asset=xxxx.xxxx.com; identifier=; category=critical; importance=0.45131093; is_ip=False},

So far I've tried to access each value with a table, but sometimes the records contains an object, which outputs System.Object[] to the CSV file.

foreach ($item in $findings.results) { 
    $tabledata = [ordered]@{
        temporary_id     = $item.temporary_id
        affects_rating   = $item.affects_rating
        asset            = $item.assets.asset
        asset_identifier = $item.assets.identifier
        asset_category   = $item.assets.category
        asset_importance = $item.assets.importance
        asset_is_ip      = $item.assets.is_ip
        modal_data       = $item.details.diligence_annotations.modal_data
        modal_tags       = $item.details.diligence_annotations.modal_tags
        server           = $item.details.diligence_annotations.server
    }
}

The type of the variable $findings is a PSCustomObject

PS C:\Users\bryanar> $findings.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                                   
-------- -------- ----                                     --------                                                                                                                                                   
True     False    PSCustomObject                           System.Object 

Any recommendations?

1

There are 1 best solutions below

0
On

Let's say I have an object $result full of properties, lists, or other objects:

$result = [pscustomobject]@{Name='Foo';Level='1'
  Object= [pscustomobject]@{Name='Bar';Level='2'
    List= @(
      [pscustomobject]@{User='John Smith';Dept='Accounting'},
      [pscustomobject]@{User='Bob Smith';Dept='Accounting'}
)}}
$result | fl

Name   : Foo
Level  : 1
Object : @{Name=Bar; Level=2; List=System.Object[]}

If you just want to see the whole object for troubleshooting/exploring purposes, I find the easiest way is to convert it to json or xml:

$result | ConvertTo-Json -Depth 10
{
  "Name":  "Foo",
  "Level":  "1",
  "Object":  {
    "Name":  "Bar",
    "Level":  "2",
    "List":  [
      {
        "User":  "John Smith",
        "Dept":  "Accounting"
      },
      {
        "User":  "Bob Smith",
        "Dept":  "Accounting"
      }
    ]
  }
}

If you want to save an object like this, use Export-CLIXML instead of CSV. It's very verbose, but great for when you need to re-use an object since it keeps the type information.