Hashtables from ConvertFrom-json have different type from powershells built-in hashtables, how do I make them the same?

前端 未结 5 1286
天命终不由人
天命终不由人 2020-12-09 10:33

I have a json file (test.json) that looks something like this:

{
    \"root\":
    {
        \"key\":\"value\"
    }
}

I\'m loading it into

相关标签:
5条回答
  • 2020-12-09 10:46

    The example was for a relatively shallow source object (not nested objects in the properties).

    Here's a version that will go 2 levels deep into the source object, and should work with your data:

    $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
    
    0 讨论(0)
  • 2020-12-09 10:46

    @Duncan: If you need to use JSON Input for an command expecting a hashmap though (eg SET-ADUSER), try something like this:

    function SetADProperties{
        param($PlannedChanges)
        $UserName = $PlannedChanges.Request.User
        $Properties = @{}
        foreach ($key in ($PlannedChanges.SetADProperties | Get-Member -MemberType NoteProperty).Name)
        {
            $Properties[$key] = $PlannedChanges.SetADProperties.$key
        }
        # Call Set-ADUser only once, not in a loop
        Set-ADUser -Identity $UserName -Replace $Properties
    }
    
    $content = Get-Content -encoding UTF8 $FileName
    $PlannedChanges = $content | ConvertFrom-Json
    SetADProperties $PlannedChanges | Write-Output
    

    Example JSON:

    {"SetADProperties":{"postalCode":"01234","l":"Duckburg","employeenumber":"012345678"},
    "Request":{"Action":"UserMove","User":"WICHKIND","Change":"CH1506-00023"}}
    
    0 讨论(0)
  • 2020-12-09 10:49

    Here's a quick function to convert a PSObject back into a hashtable (with support for nested objects; intended for use with DSC ConfigurationData, but can be used wherever you need it).

    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
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-09 10:54

    The ConvertFrom-Json cmdlet gives you a custom object so you have to access them using dot notation rather than as a subscript. Usually you would know what fields you expect in the JSON so this is actually more useful in general than getting a hash table. Rather than fighting the system by converting back to a hash table, I suggest you work with it.

    You can use select with wildcard property names to get at the properties:

    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
    

    and Get-Member if you want to extract a list of property names that you can iterate over:

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

    Putting that into a loop gives code like this:

    PS D:\> foreach ($k in ($data.root | Get-Member k* -MemberType NoteProperty).Name) {
        Write-Output "$k = $($data.root.$k)"
        }
    key = value
    key2 = value2
    
    0 讨论(0)
  • 2020-12-09 10:59

    I put this together to handle nested json to hashtables

        function ConvertJSONToHash{
        param(
            $root
        )
        $hash = @{}
    
        $keys = $root | gm -MemberType NoteProperty | select -exp Name
    
        $keys | %{
            $key=$_
            $obj=$root.$($_)
            if($obj -match "@{")
            {
                $nesthash=ConvertJSONToHash $obj
                $hash.add($key,$nesthash)
            }
            else
            {
               $hash.add($key,$obj)
            }
    
        }
        return $hash
    }
    

    I have only tested with 4 levels but recursive until it has complete hashtable.

    0 讨论(0)
提交回复
热议问题