Skip to content

Add option to ConvertFrom-Json as a Hashtable #3623

Closed

Description

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 .

Activity

  1. BrucePay commented on Apr 24, 2017

    @BrucePay
    Collaborator

    Can you provide a concrete example where hashtables are superior to an object tree?

  2. powercode commented on Apr 24, 2017

    @powercode
    Collaborator

    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'.

  3. kittholland commented on Apr 24, 2017

    @kittholland
    ContributorAuthor

    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
    
    
  4. KevinMarquette commented on Apr 25, 2017

    @KevinMarquette
    Contributor

    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.

  5. lehtoj commented on May 13, 2017

    @lehtoj

    Kevin Marquette (@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?

  6. KevinMarquette commented on May 13, 2017

    @KevinMarquette
    Contributor

    Thank you for that example. I had previously overlooked the match keyword there. I will start using that one.

  7. scrthq commented on Aug 3, 2017

    @scrthq

    +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.

  8. added
    Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributors
    on Aug 4, 2017
  9. added this to the milestone on Aug 4, 2017
  10. iSazonov commented on Oct 26, 2017

    @iSazonov
    Collaborator

    Leave a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    HacktoberfestPotential candidate to participate in HacktoberfestIssue-Enhancementthe issue is more of a feature request than a bugResolution-FixedThe issue is fixed.Up-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsWG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions