【问题标题】:Create Hashtable from JSON从 JSON 创建 Hashtable
【发布时间】:2019-11-02 15:35:02
【问题描述】:

我想得到一个像这样的 Hashtable 的 JSON 表示:

@{Path="C:\temp"; Filter="*.js"}

ConvertTo-Json 结果:

{
    "Path":  "C:\\temp",
    "Filter":  "*.js"
}

但是,如果您使用 ConvertFrom-Json 将该 JSON 字符串转换回来,您将不会得到一个 HashTable,而是一个 PSCustomObject。

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

【问题讨论】:

标签: json powershell


【解决方案1】:
$json = @{Path="C:\temp"; Filter="*.js"} | ConvertTo-Json

$hashtable = @{}

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

改编自PSCustomObject to Hashtable

【讨论】:

  • 如果哈希表中项的顺序是导入,则可以创建为$hashtable = [ordered]@{}
【解决方案2】:

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

【讨论】:

  • 在 Powershell 6.2 中为我工作
【解决方案3】:

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

【讨论】:

  • 在 PowerShell 5.1 中,我发现 $parser.DeserializeObject($text) 反序列化为 .NET 字典,而不是 Hashtable 但是,与 DeserializeObject 方法相反,Deserialize 方法确实反序列化为 Hashtable:$parser.Deserialize($text, @{}.GetType())
  • @SimonTewsi 您可以使用[hashtable] 代替@{}.GetType()
【解决方案4】:

这篇文章的答案是一个很好的开始,但是当您开始获得更复杂的 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
}

【讨论】:

    【解决方案5】:

    我相信Converting JSON to a hashtable 中提出的解决方案更接近ConvertFrom-Json 的PowerShell 6.0 实现

    我尝试了几个 JSON 源,我总是得到正确的哈希表。

    $mappings = @{
      Letters = (   
          "A",
          "B")
      Numbers        = (
          "1",
          "2",
          "3")
      Yes = 1
      False = "0"
    }
    
    # TO JSON 
    $jsonMappings = $mappings  | ConvertTo-JSON
    $jsonMappings
    
    # Back to hashtable 
    # In PowerShell 6.0 would be:
    #   | ConvertFrom-Json -AsHashtable
    $jsonMappings | ConvertFrom-Json -As hashtable
    

    【讨论】:

      【解决方案6】:

      您可以编写一个函数将 psobject 转换为哈希表。

      我在这里写了一个答案:enter link description here

      【讨论】:

      • 请将您的代码作为答案的一部分而不是链接发布,因为将来链接可能会失效
      • 链接缺少有用的描述/标题(当然没有)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-17
      • 2016-10-01
      • 2021-12-09
      • 2011-12-21
      • 2013-04-22
      • 2011-09-26
      相关资源
      最近更新 更多