0

Powershell 3.0 has a quick way to created hashtables that maintain their order as well at the cost of a slight memory expenditure.

The Problem:

# create ordered hashtable
$a = [ordered]@{}

# populate with 3 key-value pairs
$a['a'] = 15
$a['b'] = 10
$a['c'] = 9

$a
# Name                           Value
# ----                           -----
# a                              15
# b                              10
# c                              9

# get value for key = 'b'
$a['b']
# returns: 10

# get value for indexed last (ordered) item in table: This is desired behaviour
$a[-1]
# returns: 9

# show type of object for variable $a
$a | Get-Member
# returns: TypeName: System.Collections.Specialized.OrderedDictionary
# ...

All is well so far.

When serializing the object to disk, then deserializing, the object changes from System.Collections.Specialized.OrderedDictionary to Deserialized.System.Collections.Specialized.OrderedDictionary.

# serialize to disk
$a | Export-CliXml ./serialized.xml
# deserialize from disk
$d = Import-CliXml ./serialized.xml

# show datatype of deserialized object
# returns: Deserialized.System.Collections.Specialized.OrderedDictionary
# ...

# $d variable is still indexed by key, but not by integer index
$d['b']
# returns: 10

# request the first item in the dictionary by numerical index
$d[0]
# returns: nothing/null, this is undesired behaviour.  AARGH!

Naturally, I believe the deserialized Ordered Dictionary should behave as the Ordered Dictionary did before it had been persisted to disk, specifically to be able to retrieve hashtable items by numerical index as well as key.

Since that is not currently the case in Powershell, is there a quick way to convert the deserialized object to the base version of the object without doing a foreach on the entire deserialized object?

HipCzeck
  • 486
  • 3
  • 8
  • 2
    This appears to still be broken in PowerShell v5, too. You can export an `System.Collections.Specialized.OrderedDictionary`, but importing the XML results in a `System.Collections.Hashtable`. I wonder if [this](http://stackoverflow.com/questions/495647/serialize-class-containing-dictionary-member) is at all related. – Bacon Bits Dec 04 '16 at 21:55
  • Interesting. Clearly the object serializes and deserializes, it is just that the deserialized version of the object lacks some functionality of the base object. I was just hoping that the Powershell ethos of getting around pesky problems with a clever little twist would manifest. I have code to cycle through the deserialized object and rehydrate a fully functional version of the original object, but it's slow. "I hate wait!" – HipCzeck Dec 05 '16 at 15:51
  • You might try submitting an issue on the [PowerShell GitHub](https://github.com/PowerShell/PowerShell/issues). As well there's [this `ConvertTo-OrderedDictionary.ps1` script}(https://gallery.technet.microsoft.com/scriptcenter/ConvertTo-OrderedDictionary-cf2404ba) from one of the "Scripting Guys" team. The logic is dead simple, though. – Bacon Bits Dec 07 '16 at 01:31
  • Although the dotnet [`PSSerializer`](https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.psserializer?view=pscore-6.2.0) serializer appears to preserve the order, the deserializer (including `DeserializeAsList(String)`) also doesn't preserver the order. – iRon Jun 30 '19 at 15:18

1 Answers1

0

To serialize/deserialize and preserve the order of an [Ordered] object you might consider to use the ConvertTo-Expression cmdlet (see: 'Save hash table in PowerShell object notation (PSON)' question):

$Expression =  ConvertTo-Expression $a
$b = &$Expression
$b

Name                           Value
----                           -----
a                              15
b                              10
c                              9
iRon
  • 20,463
  • 10
  • 53
  • 79