I have a json file (test.json) that looks something like this:
{
\"root\":
{
\"key\":\"value\"
}
}
I\'m loading it into
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
@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"}}
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
}
}
}
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
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.