PSCustomObject到Hashtable


76

将a转换PSCustomObject为a的最简单方法是Hashtable什么?它与splat运算符,大括号和看起来像键值对的显示一样。当我尝试将其投射到[Hashtable]它不起作用时。我也尝试过.toString(),分配的变量说它是一个字符串,但是什么也不显示-有什么想法吗?


1
PSCustomObjects优于哈希表。转换前请三思。 stackoverflow.com/questions/22002748/…–
spuder

1
喷溅不适用于PSCustomObject,这是我能想到的一个很好的理由。
Brain2000

Answers:


95

不应该太难。这样的事情应该可以解决问题:

# Create a PSCustomObject (ironically using a hashtable)
$ht1 = @{ A = 'a'; B = 'b'; DateTime = Get-Date }
$theObject = new-object psobject -Property $ht1

# Convert the PSCustomObject back to a hashtable
$ht2 = @{}
$theObject.psobject.properties | Foreach { $ht2[$_.Name] = $_.Value }

请注意,$_.Name该字符串已经是一个字符串,因此$ht2[$_.Name]or$h.($_.Name)会和一样工作"$($_.Name)"
XLII皇帝

10
请注意,这不适用于由创建的PSCustomObjects ConvertFrom-Json这个问题解决了这个问题。
BenV

4
@BenV:只是要澄清一下:问题源于嵌套的自定义对象,而不是由于ConvertFrom-Json本身的使用,而后者本身也会产生[PSCustomObject]实例。换句话说:产生非嵌套对象的JSON源就可以正常工作;例如:('{ "foo": "bar" }' | ConvertFrom-Json).psobject.properties | % { $ht = @{} } { $ht[$_.Name] = $_.Value } { $ht }
mklement0 '16

2
铸造可能成为未来一个现实:connect.microsoft.com/PowerShell/feedback/details/679841/...
W1M0R

参见以下@Svyatoslav Pidgorny的答案,该答案使用PowerShell 6或7中的新功能以获得更简单的方法! stackoverflow.com/a/61742479/3425553
伊戈尔

28

Keith已经为您提供了答案,这只是单线执行此操作的另一种方式:

$psobject.psobject.properties | foreach -begin {$h=@{}} -process {$h."$($_.Name)" = $_.Value} -end {$h}

嘿,从非常相似的内容开始,只是它足够长以调用SO水平滚动条。顺便说一句,我想你$'s缺少一些_'s。:-)
Keith Hill 2010年

那就是我试图避免的事情,最终它吞噬了下划线的迹象。谢谢!
Shay Levy 2010年

@ShayLevy:将所有内容放在同一行有什么好处?
Rubanov

2
好 如果使用% 和位置参数作为块,则可以缩短为$psobject.psobject.properties | % { $ht = @{} } { $ht[$_.Name] = $_.Value } { $ht }。@Rubanov:不必位于一行上,但优点是可以由单个语句(管道)创建哈希表。
mklement0

24

这是一个也可与嵌套哈希表/数组一起使用的版本(如果您要使用DSC ConfigurationData进行此操作,这将非常有用):

function ConvertPSObjectToHashtable
{
    param (
        [Parameter(ValueFromPipeline)]
        $InputObject
    )

    process
    {
        if ($null -eq $InputObject) { return $null }

        if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string])
        {
            $collection = @(
                foreach ($object in $InputObject) { ConvertPSObjectToHashtable $object }
            )

            Write-Output -NoEnumerate $collection
        }
        elseif ($InputObject -is [psobject])
        {
            $hash = @{}

            foreach ($property in $InputObject.PSObject.Properties)
            {
                $hash[$property.Name] = ConvertPSObjectToHashtable $property.Value
            }

            $hash
        }
        else
        {
            $InputObject
        }
    }
}

3
这是唯一适用于具有多层嵌套对象和数组的数据的版本。
杰弗里·哈蒙

3
多层嵌套对象的出色且优雅的解决方案。
彼得·扎哈里亚

如前一个答案的注释所述,以上代码可处理复杂的/嵌套的哈希表,非常适合处理的内容ConvertFrom-Json。另请参阅此问题
托马斯

我无法使它按原样用于嵌套对象:@{ Name = "test1"; nested = @{ license = 'x'; cert = 'y' } } | Convert-PSObjectToHashTable 相反,我不得不GetEnumerator()在第15行添加一个:foreach ($object in $InputObject.GetEnumerator()) { ConvertPSObjectToHashtable $object }
Keith S Garner

可以在此处找到亚当·贝特拉姆
Ciove

4

我极其懒惰的方法,通过PowerShell 6中的一项新功能启用:

$myhashtable = $mypscustomobject | ConvertTo-Json | ConvertFrom-Json -AsHashTable

我喜欢这个!
伊戈尔

我希望避免使用它,因为往返于文本和返回对象格式似乎有点荒谬……但是我可以确认它不起作用,并且这是最方便的(如果不是性能很高的话)句法。
jrypkahauer

3

这适用于由ConvertFrom_Json创建的PSCustomObjects。

Function ConvertConvertFrom-JsonPSCustomObjectToHash($obj)
{
    $hash = @{}
     $obj | Get-Member -MemberType Properties | SELECT -exp "Name" | % {
                $hash[$_] = ($obj | SELECT -exp $_)
      }
      $hash
}

免责声明:我几乎不了解PowerShell,因此它可能不尽如人意。但这有效(仅适用于一个级别)。


1
多一点清洁(可能更难理解)$hash=@{};$obj | Get-Member -MemberType Properties | foreach { $hash.Add($_.Name,$obj.($_.Name))}
Adarsha

2

我的代码:

function PSCustomObjectConvertToHashtable() {
    param(
        [Parameter(ValueFromPipeline)]
        $object
    )

    if ( $object -eq $null ) { return $null }

    if ( $object -is [psobject] ) {
        $result = @{}
        $items = $object | Get-Member -MemberType NoteProperty
        foreach( $item in $items ) {
            $key = $item.Name
            $value = PSCustomObjectConvertToHashtable -object $object.$key
            $result.Add($key, $value)
        }
        return $result
    } elseif ($object -is [array]) {
        $result = [object[]]::new($object.Count)
        for ($i = 0; $i -lt $object.Count; $i++) {
            $result[$i] = (PSCustomObjectConvertToHashtable -object $object[$i])
        }
        return ,$result
    } else {
        return $object
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.