Currently ConvertFrom-Json returns a PSCustomObject. It would be nice in some cases if you could choose to return a Hashtable instead, perhaps using an -As parameter. Hashtables are often much faster for processing Json document databases compared to having to iterate through object properties.
This would also be a possible way to address #1755 .
Can you provide a concrete example where hashtables are superior to an object tree?
Apart from object size and performance, it may matter with case sensitivity. I have run into issues where I couldn't use the PowerShell cmdlets because the json contained 'Property' and 'property'.
Yes, the case sensitivity is one area, empty property names are another area.
On the performance side, I would suggest that adding, removing and enumerating properties are all slower/more difficult on a pscustomobject than a hashtable.
$hashTable = @{
"1" = 1
"2" = 2
}
$object = [pscustomobject]$hashTable
Measure-command {
Foreach($number in 3..10000)
{
$hashTable.Add("$number", $number)
}
}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 63
Ticks : 631145
TotalDays : 7.30491898148148E-07
TotalHours : 1.75318055555556E-05
TotalMinutes : 0.00105190833333333
TotalSeconds : 0.0631145
TotalMilliseconds : 63.1145
Measure-Command {
Foreach($number in 3..10000)
{
$object | Add-Member -MemberType NoteProperty -Name "$number" -Value $number
}
}
Days : 0
Hours : 0
Minutes : 0
Seconds : 1
Milliseconds : 76
Ticks : 10769741
TotalDays : 1.24649780092593E-05
TotalHours : 0.000299159472222222
TotalMinutes : 0.0179495683333333
TotalSeconds : 1.0769741
TotalMilliseconds : 1076.9741
I like the idea of an -AsHashtable option or something similar. Whenever I enumerate all the property names and then walk them, it is very inefficient. Even more so when I am recursively walking the object to turn it into a nested hashtable.
There is also not a simple way to test for a property on an object. Sometimes you can't just test for $null because the value could be $null. The existence of a property is different than a $null property value.
[bool]( $object.PSobject.Properties.name -match $property )
$hashtable.ContainsKey($property)
I also don't like using a dot property to a variable to access properties this way. A minor gripe but something that I like to avoid because at a glance it is hard to tell if that is intentional or a typo.
$object.$property
$hashtable[ $property ]
Alternatively, we could make PSCustomObject better at property enumeration, addition, and removal.
@KevinMarquette That is not exactly true that there is no simple way to test for a property.
$obj = New-Object pscustomobject -Property @{a = 1; b = 2}
$obj.psobject.Properties.Match("a")
$obj.psobject.Properties.Match("c")
Seems simple enough?
Thank you for that example. I had previously overlooked the match keyword there. I will start using that one.
+1 for this request.
For my use case, I tend to leverage JSON for config files shared between different languages (or even module settings for certain things); I typically will have a function (let's say Export-Config) that accepts a hashtable as input and pipes to ConvertTo-Json prior to setting in a file. PSObjects and Hashtables result in the same JSON structure for my use case, so I opt to have the input as a Hashtable to save some characters and allow me to build that input value with less keystrokes.
When I want to reimport that config and make updates with a separate function (let's say Update-Config), I have to adjust the function logic and deal with Add-Member vs just stating $config["Map"] = $NewSettings. Also in agreeance with Kevin in that having $hashtable[ $property ] buried in a script is easier to identify as what it is compared to $object.$property.
Speed differences between the two are also evident when dealing with very large object arrays vs large hashtables to the point where I will almost always build a hashtable from the resulting object array for lookup speed gains compared to looking up against the object array directly.
Leave a comment
Most helpful comment
Yes, the case sensitivity is one area, empty property names are another area.
On the performance side, I would suggest that adding, removing and enumerating properties are all slower/more difficult on a pscustomobject than a hashtable.