来自JSON的PowerShell Hashtable

Mar*_*arc 18 powershell json

我想得到一个Hashtable的JSON表示,如下所示:

@{Path="C:\temp"; Filter="*.js"}
Run Code Online (Sandbox Code Playgroud)

ConvertTo-Json 结果是:

{
    "Path":  "C:\\temp",
    "Filter":  "*.js"
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您将JSON字符串转换回来,ConvertFrom-Json则不会获得HashTable,而是获得PSCustomObject.

那么如何才能可靠地序列化上面的Hashmap呢?

sod*_*low 33

$json = @{Path="C:\temp"; Filter="*.js"} | ConvertTo-Json

$hashtable = @{}

(ConvertFrom-Json $json).psobject.properties | Foreach { $hashtable[$_.Name] = $_.Value }
Run Code Online (Sandbox Code Playgroud)

PSCustomObject改编为Hashtable


小智 14

这里的讨论有点晚了,但在 PowerShell 6(核心)中有一个ConvertFrom-Json-AsHashtable参数。


wOx*_*xOm 8

JavaScriptSerializer从.NET3.5开始可用(可以安装在XP上,包含在Win7和更新版本中),它比Convert-FromJSON快几倍,它可以正确解析嵌套对象,数组等.

function Parse-JsonFile([string]$file) {
    $text = [IO.File]::ReadAllText($file)
    $parser = New-Object Web.Script.Serialization.JavaScriptSerializer
    $parser.MaxJsonLength = $text.length
    Write-Output -NoEnumerate $parser.DeserializeObject($text)
}
Run Code Online (Sandbox Code Playgroud)

  • @SimonTewsi 您可以使用“[hashtable]”代替“@{}.GetType()”。 (4认同)
  • 在PowerShell 5.1中,我发现`$ parser.DeserializeObject($ text)`反序列化为.NET字典而不是Hashtable但是,与DeserializeObject方法相反,Deserialize方法反序列化为Hashtable:`$ parser.Deserialize ($ text,@ {}.GetType())`. (2认同)

小智 6

这篇文章的答案是一个很好的开始,但是当您开始获得更复杂的 json 表示形式时就有点天真了。

下面的代码将解析嵌套的 json 数组和 json 对象。

[CmdletBinding]
function Get-FromJson
{
    param(
        [Parameter(Mandatory=$true, Position=1)]
        [string]$Path
    )

    function Get-Value {
        param( $value )

        $result = $null
        if ( $value -is [System.Management.Automation.PSCustomObject] )
        {
            Write-Verbose "Get-Value: value is PSCustomObject"
            $result = @{}
            $value.psobject.properties | ForEach-Object { 
                $result[$_.Name] = Get-Value -value $_.Value 
            }
        }
        elseif ($value -is [System.Object[]])
        {
            $list = New-Object System.Collections.ArrayList
            Write-Verbose "Get-Value: value is Array"
            $value | ForEach-Object {
                $list.Add((Get-Value -value $_)) | Out-Null
            }
            $result = $list
        }
        else
        {
            Write-Verbose "Get-Value: value is type: $($value.GetType())"
            $result = $value
        }
        return $result
    }


    if (Test-Path $Path)
    {
        $json = Get-Content $Path -Raw
    }
    else
    {
        $json = '{}'
    }

    $hashtable = Get-Value -value (ConvertFrom-Json $json)

    return $hashtable
}
Run Code Online (Sandbox Code Playgroud)