1

I used BinaryFormatter which is now obsolete, to (de)serialize Hashtable objects.

Hashtables are tricky as they can wrap anything, including other Hashtables:

[ "fruits": [ "apple":10, "peach":4, "raspberry":5 ], "vegetables": [ "lettuce":5 ]
  "animals": [ "with4legs": [ "cat":15, "dog":2 ], "withwings": [ "bird":51 ]
]

BinaryFormatter could perfectly serialize these Hashtables (under dotNET 4.8):

Hashtable main = new Hashtable();

Hashtable fruits = new Hashtable()
{
    { "apple", 10 },
    { "peach", 4 },
    { "raspberry", 5 }
};
Hashtable vegetables = new Hashtable()
{
    { "lettuce", 5 }
};
Hashtable with4legs = new Hashtable()
{
    { "cat", 15 },
    { "dog", 2 }
};
Hashtable withwings = new Hashtable()
{
    { "bird", 51 }
};
Hashtable animals = new Hashtable()
{
    { "with4legs", with4legs },
    { "withwings", withwings }
};

main.Add("fruits", fruits);
main.Add("vegetable", vegetables);
main.Add("animals", animals);

BinaryFormatter binaryFormatter = new BinaryFormatter();
using (Stream stream = new FileStream("Test.file", FileMode.Create))
{
    binaryFormatter.Serialize(stream, main);
}

The file is somewhat messy:

enter image description here

However, when reading it back with the BinaryFormatter:

Hashtable newMain = new Hashtable();
using (Stream stream = new FileStream("Test.file", FileMode.OpenOrCreate))
{
    newMain = (Hashtable)binaryFormatter.Deserialize(stream);
}

It could perfectly reassemble the Hashtable:

enter image description here

Now, with dotNET, BinaryFormatter is obsolete, and XmlSerializer or JsonSerializer is recommended to be used instead:

using (Stream stream = new FileStream("Test.file", FileMode.Create))
{
    JsonSerializer.Serialize(stream, main);
}

File is in JSON format now:

enter image description here

And unfortunately when deserializing it:

Hashtable newMain = new Hashtable();
using (Stream stream = new FileStream("Test.file", FileMode.OpenOrCreate))
{
    newMain = (Hashtable)JsonSerializer.Deserialize<Hashtable>(stream);
}

Hashtable loses its structure:

enter image description here

I did also try with MessagePack: https://msgpack.org, but I can't make it to go below one level either:

enter image description here

Now I know there can be more efficient or robust solution for this than Hashtable, but still, is there a way to move from BinaryFormatter to any recommendation which can handle saving and reloading this structure?

Daniel
  • 2,318
  • 2
  • 22
  • 53
  • Try Json.NET with [TypeNameHandling setting](https://www.newtonsoft.com/json/help/html/serializetypenamehandling.htm). It should work. – Alexander Petrov Jan 22 '23 at 10:49
  • Look at this [article](https://www.codeproject.com/Articles/5284591/Adding-type-to-System-Text-Json-Serialization-like). – Alexander Petrov Jan 22 '23 at 10:50
  • If you want an alternative binary serializer you can try [mine](https://github.com/koszeggy/KGySoft.CoreLibraries#binary-serialization). You can try it [online](https://dotnetfiddle.net/T7BUyB), just adjust the test to use a `Hashtable`. But bear in mind that binary serialization is generally not safe between remote entities (see more details [here](https://stackoverflow.com/a/67107584/5114784)). – György Kőszeg Jan 22 '23 at 13:22
  • If security is critical you can use .NET's built-in non-polymorphic text-based serializers (`XmlSerializer`, `JsonSerializer`), though they will have issues with a `HashTable` that can contain literally anything. If security is not that critical, polymorhic serializers such as Json.NET or my [`XmlSerializer`](https://github.com/koszeggy/KGySoft.CoreLibraries#xml-serialization) can also be a possible choice. The latter can usually handle a `Hashtable` without any problem if you enable the `RecursiveSerializationAsFallback` option. You can try it [online](https://dotnetfiddle.net/M2dfrx), too. – György Kőszeg Jan 22 '23 at 13:29
  • I wish to store some parameters for my application between runs. Is my assumption right here that this is not considered as "remote entities"? – Daniel Jan 22 '23 at 15:26
  • @AlexanderPetrov: by Json.NET, you are referring to Newtonsoft.Json? – Daniel Jan 22 '23 at 17:20
  • 1
    @Daniel: Deserializing a configuration from file can be considered insecure because the file can be manipulated. But it can be alright for a simple application, and that's what I also use my [`XmlSerializer`](https://github.com/koszeggy/KGySoft.CoreLibraries#xml-serialization) for. You might want to use safe mode, which prevents loading new assemblies, even if a manipulated file contains types with assembly qualified names. – György Kőszeg Jan 23 '23 at 09:07
  • 1
    And yes, Json.NET is Newtonsoft.Json. As it is also able to parse any types it can be [exploited](https://systemweakness.com/exploiting-json-serialization-in-net-core-694c111faa15?gi=ce07839c196e) for security attacks. The new built-in `JsonSerializer` addresses this issue but it has a cost: deserializing a `Hashtable` with potentially many types is not very straightforward. Again, if security is not that critical for your app you can choose the convenient way. – György Kőszeg Jan 23 '23 at 09:36

0 Answers0