PSCustomObject đến Hashtable


77

Cách dễ nhất để chuyển đổi a PSCustomObjectthành a là Hashtablegì? Nó hiển thị giống như một với toán tử splat, dấu ngoặc nhọn và những gì có vẻ là cặp giá trị khóa. Khi tôi cố gắng truyền nó đến [Hashtable]nó không hoạt động. Tôi cũng đã thử .toString()và biến được gán cho biết nó là một chuỗi nhưng không hiển thị gì - bất kỳ ý tưởng nào?


1
PSCustomObjects có lợi thế hơn so với hashtable. Hãy suy nghĩ kỹ trước khi chuyển đổi nó. stackoverflow.com/questions/22002748/…
spuder

1
Splatting không hoạt động với PSCustomObject, là một lý do chính đáng mà tôi có thể nghĩ ra.
Brain2000

Câu trả lời:


98

Không nên quá khó. Một cái gì đó như thế này sẽ thực hiện thủ thuật:

# 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 }

Lưu ý rằng $_.Nameđã là một chuỗi, vì vậy $ht2[$_.Name]hoặc $h.($_.Name)sẽ hoạt động tốt như vậy "$($_.Name)".
Emperor XLII

12
Lưu ý rằng điều này không hoạt động đối với PSCustomObject được tạo bởi ConvertFrom-Json. Câu hỏi này giải quyết vấn đề đó.
BenV

4
@BenV: Chỉ cần làm rõ: Vấn đề bắt nguồn từ các đối tượng tùy chỉnh lồng nhau , không phải từ việc sử dụng ConvertFrom-Jsonmỗi cái, cũng tạo ra các [PSCustomObject]phiên bản. Nói cách khác: một nguồn JSON tạo ra các đối tượng không lồng nhau hoạt động tốt; ví dụ:('{ "foo": "bar" }' | ConvertFrom-Json).psobject.properties | % { $ht = @{} } { $ht[$_.Name] = $_.Value } { $ht }
mklement0

2
Truyền có thể trở thành hiện thực trong tương lai: connect.microsoft.com/PowerShell/feedback/details/679841/…
W1M0R Ngày

Hãy xem câu trả lời dưới đây từ @Svyatoslav Pidgorny đang sử dụng các tính năng mới trong PowerShell 6 hoặc 7 để có cách tiếp cận đơn giản hơn! stackoverflow.com/a/61742479/3425553
Igor

28

Keith đã cho bạn câu trả lời, đây chỉ là một cách khác để thực hiện tương tự với một lớp lót:

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

Heh, bắt đầu với một cái gì đó rất giống nhau ngoại trừ nó chỉ đủ dài để gọi thanh cuộn ngang SO. BTW Tôi nghĩ rằng bạn $'sđang thiếu một số _'s. :-)
Keith Hill,

Đó là những gì tôi đã cố gắng tránh và cuối cùng nó đã nuốt dấu gạch dưới. Cảm ơn!
Shay Levy

@ShayLevy: Lợi thế của việc đặt mọi thứ trên cùng một đường thẳng là gì?
Rubanov

2
Đẹp; nếu bạn sử dụng % và tham số vị trí làm khối, bạn có thể rút ngắn thành $psobject.psobject.properties | % { $ht = @{} } { $ht[$_.Name] = $_.Value } { $ht }. @Rubanov: Nó không nhất thiết phải nằm trên một dòng duy nhất , nhưng lợi thế là một câu lệnh duy nhất (đường ống dẫn) tạo ra bảng băm.
mklement0

24

Đây là một phiên bản cũng hoạt động với các hashtable / mảng lồng nhau (rất hữu ích nếu bạn đang cố gắng thực hiện việc này với 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
Đây là phiên bản duy nhất hoạt động cho dữ liệu của tôi với các đối tượng và mảng lồng nhau nhiều cấp.
Jeffrey Harmon

3
Giải pháp tuyệt vời và thanh lịch cho các đối tượng lồng ghép nhiều cấp độ.
Petru Zaharia

Như đã lưu ý trong nhận xét của câu trả lời trước đó, đoạn mã trên xử lý các hashtable phức tạp / lồng nhau và rất tốt để xử lý nội dung từ ConvertFrom-Json. Xem thêm câu hỏi này
Thomas

Tôi không thể có được điều này để làm việc "như nó vốn có" cho các đối tượng lồng nhau: @{ Name = "test1"; nested = @{ license = 'x'; cert = 'y' } } | Convert-PSObjectToHashTable Thay vào đó, tôi đã có thêm một GetEnumerator()ngày Line 15:foreach ($object in $InputObject.GetEnumerator()) { ConvertPSObjectToHashtable $object }
Keith S Garner

Có thể tìm thấy mã tương tự của Adam Bertram ở đây: 4sysops.com/archives/convert-json-to-a-powershell-hash-table
Ciove

4

Cách tiếp cận cực kỳ lười biếng của tôi, được kích hoạt bởi một tính năng mới trong PowerShell 6:

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

Tôi thích cái này!
Igor

Tôi đã hy vọng tránh sử dụng điều này, bởi vì nó có vẻ vô lý khi thực hiện một chuyến đi vòng quanh văn bản và quay lại định dạng đối tượng ... nhưng tôi có thể xác nhận rằng nó không hoạt động và nó thuận tiện nhất (nếu không hiệu quả) cú pháp.
jrypkahauer

3

Điều này hoạt động đối với PSCustomObject được tạo bởi ConvertFrom_Json.

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

Tuyên bố từ chối trách nhiệm: Tôi hầu như không hiểu về PowerShell vì vậy điều này có thể không rõ ràng như nó có thể. Nhưng nó hoạt động (chỉ cho một cấp độ).


1
Sạch sẽ hơn một chút (có thể khó hiểu hơn)$hash=@{};$obj | Get-Member -MemberType Properties | foreach { $hash.Add($_.Name,$obj.($_.Name))}
Adarsha

2

Mã của tôi:

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
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.