39

I want to get a JSON representation of a Hashtable such as this:

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

ConvertTo-Json results in:

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

However, if you convert that JSON string back with ConvertFrom-Json you don't get a HashTable but a PSCustomObject.

So how can one reliably serialize the above Hashmap?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Marc
  • 13,011
  • 11
  • 78
  • 98
  • Possible duplicate of [PSCustomObject to Hashtable](http://stackoverflow.com/questions/3740128/pscustomobject-to-hashtable) – Martin Brandl Nov 08 '16 at 20:58

7 Answers7

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

$hashtable = @{}

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

Adapted from PSCustomObject to Hashtable

Community
  • 1
  • 1
sodawillow
  • 12,497
  • 4
  • 34
  • 44
20

A little late to the discussion here, but in PowerShell 6 (Core) there is a -AsHashtable parameter in ConvertFrom-Json.

ThePoShWolf
  • 311
  • 2
  • 3
15

JavaScriptSerializer is available since .NET3.5 (may be installed on XP, included in Win7 and newer), it's several times faster than Convert-FromJSON and it properly parses nested objects, arrays 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)
}
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • 4
    In PowerShell 5.1 I found that `$parser.DeserializeObject($text)` deserialized to a .NET Dictionary, not a Hashtable However, the Deserialize method, as opposed to the DeserializeObject method, does deserialize to a Hashtable: `$parser.Deserialize($text, @{}.GetType())` . – Simon Elms Jan 03 '18 at 09:49
  • 2
    @SimonTewsi You can use `[hashtable]` instead of `@{}.GetType()`. – beatcracker Sep 18 '19 at 15:07
5

The answer for this post is a great start, but is a bit naive when you start getting more complex json representations.

The code below will parse nested json arrays and json objects.

[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
}
Esten Rye
  • 51
  • 1
  • 1
  • This does not reconstitute empty lists correctly. [] should become a 0-length list, not null. – Blaine Jun 14 '22 at 01:21
4

I believe the solution presented in Converting JSON to a hashtable is closer to the PowerShell 6.0 implementation of ConvertFrom-Json

I tried with several JSON sources and I always got the right hashtable.

$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
Gonzalo Contento
  • 857
  • 9
  • 21
0

import the code from link here https://4sysops.com/archives/convert-json-to-a-powershell-hash-table/

function ConvertTo-Hashtable {
[CmdletBinding()]
[OutputType('hashtable')]
param (
    [Parameter(ValueFromPipeline)]
    $InputObject
)

process {
    ## Return null if the input is null. This can happen when calling the function
    ## recursively and a property is null
    if ($null -eq $InputObject) {
        return $null
    }

    ## Check if the input is an array or collection. If so, we also need to convert
    ## those types into hash tables as well. This function will convert all child
    ## objects into hash tables (if applicable)
    if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
        $collection = @(
            foreach ($object in $InputObject) {
                ConvertTo-Hashtable -InputObject $object
            }
        )

        ## Return the array but don't enumerate it because the object may be pretty complex
        Write-Output -NoEnumerate $collection
    } elseif ($InputObject -is [psobject]) { ## If the object has properties that need enumeration
        ## Convert it to its own hash table and return it
        $hash = @{}
        foreach ($property in $InputObject.PSObject.Properties) {
            $hash[$property.Name] = ConvertTo-Hashtable -InputObject $property.Value
        }
        $hash
    } else {
        ## If the object isn't an array, collection, or other object, it's already a hash table
        ## So just return it.
        $InputObject
    }
}

} We can then call this function via pipeline: $json | ConvertFrom-Json | ConvertTo-HashTable

-2

you can write a function convert psobject to hashtable.

I wrote a answer here:enter link description here

Hu Xinlong
  • 27
  • 4