ConvertFrom-json的哈希表与powershells内置哈希表有不同的类型,我如何使它们相同?

bra*_*rad 15 powershell json

我有一个json文件(test.json),看起来像这样:

{
    "root":
    {
        "key":"value"
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用类似这样的东西将它加载到powershell中:

PS > $data = [System.String]::Join("", [System.IO.File]::ReadAllLines("test.json")) | ConvertFrom-Json

root
----
@{key=value}
Run Code Online (Sandbox Code Playgroud)

我希望能够枚举由json文件定义的'hashtable'之类的对象的键. 所以,理想情况下,我希望能够做到这样的事情:

$data.root.Keys
Run Code Online (Sandbox Code Playgroud)

并得到["关键"].我可以使用PowerShell中的内置哈希表来做到这一点,但是使用从json加载的哈希表来做这件事并不那么明显.

在对此进行故障排除时,我注意到ConvertFrom-json返回的字段与Powershell的哈希表的字段类型不同.例如,在内置哈希表上调用.GetType()会显示它的类型为'Hashtable':

PS > $h = @{"a"=1;"b"=2;"c"=3}
PS > $h.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Hashtable                                System.Object
Run Code Online (Sandbox Code Playgroud)

为我的json对象做同样的事情会产生PSCustomObject:

PS > $data.root.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object
Run Code Online (Sandbox Code Playgroud)

有没有办法将此对象转换或转换为典型的PowerShell Hashtable?

Dun*_*can 12

ConvertFrom-Jsoncmdlet将让你自定义对象,所以你必须使用点符号来访问它们,而不是作为一个下标.通常你会知道你在JSON中期望的字段,所以这实际上比获取哈希表更有用.我建议您使用它,而不是通过转换回哈希表来对抗系统.

您可以使用select通配符属性名来获取属性:

PS D:\> $data = @"
{
    "root":
    {
        "key":"value", "key2":"value2", "another":42
    }
}
"@ | ConvertFrom-Json

PS D:\> $data.root | select * | ft -AutoSize

key   key2   another
---   ----   -------
value value2      42



PS D:\> $data.root | select k* | ft -AutoSize

key   key2  
---   ----  
value value2
Run Code Online (Sandbox Code Playgroud)

Get-Member如果要提取,你可以遍历属性名称的列表:

PS D:\> ($data.root | Get-Member -MemberType NoteProperty).Name
another
key
key2
Run Code Online (Sandbox Code Playgroud)

将它放入循环可以得到如下代码:

PS D:\> foreach ($k in ($data.root | Get-Member k* -MemberType NoteProperty).Name) {
    Write-Output "$k = $($data.root.$k)"
    }
key = value
key2 = value2
Run Code Online (Sandbox Code Playgroud)


小智 9

这是一个快速函数,用于将PSObject转换回哈希表(支持嵌套对象;旨在与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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


mjo*_*nor 3

该示例针对相对较浅的源对象(不是属性中的嵌套对象)。

这是一个深入源对象 2 层的版本,并且应该适用于您的数据:

$data = @{}

foreach ($propL1 in $x.psobject.properties.name)
   {
     $data[$propL1] = @{}
     foreach ($propL2 in $x.$propL1.psobject.properties.name)
        {
          $data[$PropL1][$PropL2] = $x.$propL1.$propL2
        }
    }


$data.root.keys

key
Run Code Online (Sandbox Code Playgroud)