简体   繁体   中英

How can I generate an array of PSCustomObjects from an array of hashes in Powershell v3?

Suppose I have an array of hashes in Powershell v3:

> $hashes = 1..5 | foreach { @{Name="Item $_"; Value=$_}}

I can convert a single hash into a PSCustomObject like this:

> $co = [PSCustomObject] $hashes[0]
> $co | ft -AutoSize

Value Name  
----- ----  
    1 Item 1

> $co.GetType()

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

So far, so good. The problem occurs when I try to convert the entire hash array into PSCustomObjects in a pipeline:

> ($hashes | foreach { [PSCustomObject] $_})[0].getType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     -------- 
True     True     Hashtable                                System.Object

As you see, I'm getting an array of Hashtable objects, not PSCustomObjects . Why do I get different behavior, and how can I accomplish what I want?

Thanks.

Instead of casting, try calling New-Object directly:

# > ($hashes | foreach { New-Object -TypeName PSCustomObject -Property $_})[0].getType()

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

Also, oddly, this seems to work:

# > (0..4 |  foreach { ([PSCustomObject]$hashes[$_])})[0].GetType()

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

Why? I have no idea, it seems to have trouble performing the cast using a pipelined hashtable entry.

I have yet to figure out the exact cause (Everyone is still learning something) but your issue is related to the $_ pipe element somehow. I can make your code work if I force a cast of the $_

$hashes = 1..5 | foreach { @{Name="Item $_"; Value=$_}}
$hashes | %{([pscustomobject][hashtable]$_)}

Output

Value Name  
----- ----  
    1 Item 1
    2 Item 2
    3 Item 3
    4 Item 4
    5 Item 5

Something curious

I didn't like Name and Value , while I was testing (That is what a literal hash table had for headers and I found it confusing while I was testing), so I changed the later to Data and then the output differs. I only post it as it is curious. It is hard to show the results in the post.

Name                                                                                                                                                     Data
----                                                                                                                                                     ----
Item 1                                                                                                                                                      1
Item 2                                                                                                                                                      2
Item 3                                                                                                                                                      3
Item 4                                                                                                                                                      4
Item 5                                                                                                                                                      5

This seems to work:

$hashes = 1..5 | foreach { @{Name="Item $_"; Value=$_}}

foreach ($hash in $hashes)
{([PSCustomObject]$hash).gettype()}

It seems that value of pipeline variable $_ get wrapped into PSObject and that break cast to PSCustomObject .

> $hashes=@{Value=1},[PSObject]@{Value=2}

> $hashes[0].GetType().FullName
System.Collections.Hashtable
> $hashes[1].GetType().FullName
System.Collections.Hashtable
# It seems that both $hashes elements are Hashtable,

> [Type]::GetTypeArray($hashes).FullName
System.Collections.Hashtable
System.Management.Automation.PSObject
# But, as you can see, second one is not.

> ([PSCustomObject]$hashes[0]).GetType().FullName
System.Management.Automation.PSCustomObject
> ([PSCustomObject]$hashes[1]).GetType().FullName
System.Collections.Hashtable
# And that difference break cast to PSCustomObject.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM