izSaad
izSaad

Reputation: 589

Powershell variable not displaying nested object

I am sending a GET request that returns an object. Using postman, I get:

{
"changedInstance": {
    "change": "Created",
    "instanceAfterChange": {
        "instanceId": "123",
        "schemaName": "RBAC",
        "className": "PermissionCategory",
        "properties": {
            "Name": "IModel Schema Management Service",
            "TypeId": 2,
            "TypeName": "Service Access and Permissions"
        }
    }
}}

But when I send a request through Powershell, I get the response:

@{change=Created; instanceAfterChange=}

The request I have made:

$Response = Invoke-RestMethod -Uri $base_url/v2.4/Repositories/BentleyCONNECT--Main/RBAC/PermissionCategory -Method Post -Headers @{'Authorization' = 'Bearer ' + $global:token} -Body $postParams -ContentType "application/json"

I have checked all the header values and the body, no values are missing.

The property 'instanceAfterChange' is empty, however when I monitor this same request in fiddler, it shows the correct response. My question is, why is Powershell displaying it as empty even though when it is not.

Upvotes: 4

Views: 544

Answers (1)

mklement0
mklement0

Reputation: 437418

ConvertFrom-Json constructs a [pscustomobject] instance from your JSON input, and what you're seeing (@{change=Created; instanceAfterChange=}) is the default display formatting for the instance's .changedInstance property value.

Due to a bug as of PowerShell 7.0, the default display formatting makes it appear as if property instanceAfterChange is empty, but it actually isn't.

  • Specifically, the bug is that calling .ToString() on [pscustomobject] instances unexpectedly yields the empty string - see this GitHub issue.

  • The hashtable-like display representation of [pscustomobject]s as property values - as shown in your question and explained in this answer - involves .ToString() calls on nested [pscustomobject] instances, which is why the bug surfaces.

Therefore, you shouldn't have a problem accessing the nested [pscustomobject]s' properties, e.g., $convertedFromJson.changedInstance.instanceAfterChange.schemaName should yield RBAC.

An easy way to verify that the data is there is to convert back to JSON (ConvertTo-Json) or to visualize the structure via Format-Custom.

A simplified example:

$convertedFromJson = '{
  "changedInstance": {
    "instanceAfterChange": {
      "instanceId": "123",
      "schemaName": "RBAC"
    }
  }
}
' | ConvertFrom-Json

# Output as-is: the bug makes .changedInstance appear empty.
$convertedFromJson

'---'

# Access a nested property - this works.
$convertedFromJson.changedInstance.instanceAfterChange.schemaName

'---'

# Visualize the structure of the nested object.
$convertedFromJson | Format-Custom

The above yields:

changedInstance
---------------
@{instanceAfterChange=}  # DISPLAY BUG: .instanceAfterChange appears empty.
---
RBAC # OK: accessing a property of .instanceAfterChange works.
---

# Visualization of the nested object's structure via Format-Custom
class PSCustomObject
{
  changedInstance = 
    class PSCustomObject
    {
      instanceAfterChange = 
        class PSCustomObject
        {
          instanceId = 123
          schemaName = RBAC
        }
    }
}


Upvotes: 3

Related Questions