Skip to content

Make PSCustomObject more Dictionary alike #20591

@iRon7

Description

@iRon7

Summary of the new feature / enhancement

Use case:
I have a Complex Object1) like:

$MyObject | ConvertTo-Json -Depth 9
{
  "AllNodes": [
    {
      "NodeName": "localhost",
      "CertificateFile": ".\\DSCCertificate.Customer.cer"
    }
  ],
  "NonNodeData": {
    "Exchange": {
      "CASMailboxPlans": [
        {
          "ImapEnabled": true,
          "Identity": "ExchangeOnlineEnterprise-4aad1894-b847-4488-bb47-df02c2f2aef4"
        },
        {
          "ImapEnabled": true,
          "Identity": "ExchangeOnlineDeskless-3967a644-75e7-44fc-a644-ce517aa649b3"
        }
      ],
      "OrganizationConfig": {
        "ActivityBasedAuthenticationTimeoutEnabled": false
      }
    }
  }
}

I would like to recursively iterate through the object to do things along with merging certain properties with a similar object.
You probably want to know whether $MyObject contains HashTables (aka dictionaries) or PowerShell Objects (PSCustomObjects).
Why? because it currently matters for scripting the required iterator.
But I don't think it should be the case if the PSCustomObject type would have a few additional methods and implementations that are similar to a dictionary syntax.

Note that adding helper functions to determine the type of the (recursive) nodes and react on it could get pretty expensive for recursive cmdlets (https://github.com/orgs/PowerShell/discussions/19322).

  1. As an aside, I wonder whether there is a specific name for these complex/recurse objects (as apposed to a flat object).

Proposed technical implementation details (optional)

Adding a few (hidden) methods would allow for a common iteration whether it concerns a Dictionary or a PSCustomObject:

$HashTable = @{ a = 1; b = 2 }
$PSCustomObject = [PSCustomObject]$HashTable # $PSCustomObject = $HashTable | ConvertTo-Json -Depth 9 | ConvertFrom-Json
$PSCustomObject | Add-Member -MemberType ScriptMethod -Name 'get_Count'     -Value { @($this.PSObject.Properties).get_Count() }
$PSCustomObject | Add-Member -MemberType ScriptMethod -Name 'get_Keys'      -Value { $this.PSObject.Properties.Name }
$PSCustomObject | Add-Member -MemberType ScriptMethod -Name 'get_Values'    -Value { $this.PSObject.Properties.Value }
$PSCustomObject | Add-Member -MemberType ScriptMethod -Name 'getEnumerator' -Value { $this.PSObject.Properties }

foreach ($Key in $HashTable.get_Keys()) { $Key }
foreach ($Key in $PSCustomObject.get_Keys()) { $Key }

In addition it would be helpful (if even possible) to be able to use index notation ( bracket address) for the PSCustomObject properties . Aside that this would give a common StrictMode compliant read access to the properties:

$HashTable['a'] #  returns 1
$PSCustomObject['a'] # also returns 1 (Wishful thinking)

It would imply a common and easy way to add properties to a PowerShell object (rather using Add-Member).

$HashTable['c'] = 3 # creates a new entry
$PSCustomObject['c'] = 3 # also creates a new entry/property (Wishful thinking)

Just another very common use case: Add a new column in CSV file by using existing columns

Wishful thinking:

Import-Csv 'C:\test.csv' | Foreach-Object {
    $CSVData['samAccountName'] = (Get-ADUser -Filter "GivenName -eq '$_.Name' -and SurName -eq '$_.Surname'").samAccountName
} | Export-Csv 'C:\output.csv

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugNeeds-TriageThe issue is new and needs to be triaged by a work group.WG-Languageparser, language semanticsWG-NeedsReviewNeeds a review by the labeled Working Group

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions