84 votes

PSCustomObject en Hashtable

Quel est le moyen le plus simple de convertir un PSCustomObject en un Hashtable? Il s'affiche comme tel avec l'opérateur de déploiement, les accolades et ce qui semblent être des paires clé-valeur. Lorsque j'essaie de le convertir en [Hashtable], cela ne fonctionne pas. J'ai également essayé .toString() et la variable assignée indique que c'est une chaîne de caractères mais n'affiche rien - des idées ?

1 votes

Les objets PSCustom ont des avantages par rapport aux tableaux de hachage. Réfléchissez à deux fois avant de le convertir. stackoverflow.com/questions/22002748/…

2 votes

Le splatting ne fonctionne pas avec un PSCustomObject, est une bonne raison à laquelle je pense.

110voto

Keith Hill Points 73162

Ne devrait pas être trop difficile. Quelque chose comme ça devrait faire l'affaire :

# Créez un PSCustomObject (ironiquement en utilisant une table de hachage)
$ht1 = @{ A = 'a'; B = 'b'; DateTime = Get-Date }
$theObject = new-object psobject -Property $ht1

# Convertir le PSCustomObject en une table de hachage
$ht2 = @{}
$theObject.psobject.properties | Foreach { $ht2[$_.Name] = $_.Value }

1 votes

Notez que $_.Name est déjà une chaîne de caractères, donc $ht2[$_.Name] ou $h.($_.Name) fonctionneront tout aussi bien que "$($_.Name)".

16 votes

Notez que cela ne fonctionne pas pour les objets PSCustom créés par ConvertFrom-Json. Cette question aborde ce problème.

4 votes

@BenV: Juste pour clarifier: Le problème provient d'objets personnalisés imbriqués, et non de l'utilisation de ConvertFrom-Json en soi, qui produit également des instances de [PSCustomObject]. En d'autres termes: une source JSON produisant des objets non imbriqués fonctionne très bien; par exemple: ('{ "foo": "bar" }' | ConvertFrom-Json).psobject.properties | % { $ht = @{} } { $ht[$_.Name] = $_.Value } { $ht }

36voto

Shay Levy Points 41404

Keith vous a déjà donné la réponse, voici simplement une autre façon de faire la même chose avec une seule ligne :

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

0 votes

Héh, a commencé avec quelque chose de très similaire sauf que c'était juste assez long pour invoquer la barre de défilement horizontale de SO. Au fait, je pense que vos $'s manquent de certains _'s. :-)

0 votes

C'est ce que j'essayais d'éviter et finalement il a avalé le signe de soulignement. Merci!

0 votes

@ShayLevy: Quel est l'avantage de tout mettre sur la même ligne?

30voto

Dave Wyatt Points 1209

Voici une version qui fonctionne avec des hashtable / tableaux imbriqués, ce qui est utile si vous essayez de le faire avec 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).PSObject.BaseObject
            }

            $hash
        }
        else
        {
            $InputObject
        }
    }
}

3 votes

C'est la seule version qui a fonctionné pour mes données avec des objets et des tableaux imbriqués à plusieurs niveaux.

3 votes

Excellente & élégante solution pour les objets imbriqués à plusieurs niveaux.

0 votes

Comme indiqué dans le commentaire d'une réponse précédente, ce code ci-dessus gère des hashtables complexes / imbriquées et est idéal pour gérer le contenu de ConvertFrom-Json. Voir également cette question

16voto

Mon approche extrêmement paresseuse, rendue possible par une nouvelle fonctionnalité de PowerShell 6:

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

0 votes

J'aime celui-ci!

0 votes

Je espérais éviter d'utiliser cela, car il semble un peu absurde de faire un aller-retour vers le texte et revenir à un format objet... mais je peux confirmer que cela ne fonctionne pas, et c'est la syntaxe la plus pratique (même si non performante).

0 votes

@jrypkahauer: Je suppose que tu voulais dire "ça fonctionne"?

3voto

mhenry1384 Points 3608

Cela fonctionne pour les objets personnalisés PSCreated by ConvertFrom_Json.

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

Avis de non-responsabilité : Je comprends à peine PowerShell, donc cela n'est probablement pas aussi propre que cela pourrait l'être. Mais cela fonctionne (pour un seul niveau seulement).

1 votes

Un peu plus propre (peut-être plus difficile à comprendre) $hash=@{};$obj | Get-Member -MemberType Properties | foreach { $hash.Add($_.Name,$obj.($_.Name))}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X