web-dev-qa-db-fra.com

Créer une table de hachage à partir de JSON

Je veux obtenir une représentation JSON d'une table de hachage telle que celle-ci:

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

ConvertTo-Json résulte en:

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

Cependant, si vous reconvertissez cette chaîne JSON avec ConvertFrom-Json vous n'obtenez pas un HashTable mais un PSCustomObject.

Alors, comment sérialiser de manière fiable le Hashmap ci-dessus?

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

$hashtable = @{}

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

Adapté de PSCustomObject to Hashtable

30
sodawillow

JavaScriptSerializer est disponible depuis .NET3.5 (peut être installé sur XP, inclus dans Win7 et plus récent), il est plusieurs fois plus rapide que Convert-FromJSON et il analyse correctement les objets imbriqués, les tableaux, etc.

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

La réponse à ce message est un excellent début, mais est un peu naïve lorsque vous commencez à obtenir des représentations json plus complexes.

Le code ci-dessous analysera les tableaux json imbriqués et les objets 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
}
3
Esten Rye

Un peu tard pour la discussion ici, mais dans PowerShell 6 (Core) il y a un -AsHashtable paramètre dans ConvertFrom-Json .

3
ThePoShWolf

Je pense que la solution présentée dans Conversion de JSON en table de hachage est plus proche de l'implémentation PowerShell 6.0 de ConvertFrom-Json

J'ai essayé avec plusieurs sources JSON et j'ai toujours eu la bonne table de hachage.

$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
3
Gonzalo Contento