52

Just curious as to why Dictionary is not supported by XmlSerializer?

You can get around it easily enough by using DataContractSerializer and writing the object to a XmlTextWriter, but what are the characteristics of a Dictionary that makes it difficult for a XmlSerializer to deal with considering it's really an array of KeyValuePairs.

In fact, you can pass an IDictionary<TKey, TItem> to a method expecting an IEnumerable<KeyValuePairs<TKey, ITem>>.

theburningmonk
  • 15,701
  • 14
  • 61
  • 104

3 Answers3

33

Hashtables need hashcode and equality comparer providers generally. These cant be serialized easily in XML, and definitely will not be portable.

But I think you already found your answer. Just serialize the hashtable as a List<KeyValuePair<K,V>> and then (re)construct it into a hashtable.

leppie
  • 115,091
  • 17
  • 196
  • 297
  • 4
    Or use that code: http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx – prostynick May 26 '10 at 09:30
  • 4
    What methods/properties in Dictionary imply it must be implemented as a hash table? Dictionary and IDictionary are collections of Key/Value pairs and are distinct from the Hashtable implementation. From a serialization perspective our goal seems to be to take data out of volatile memory to be able to load it back in at a later time. Reloading *any* data into a different concrete implementation of an interface is going to result in different behavior. – Jeremy Jun 16 '11 at 12:48
  • 4
    Serializing KeyValuePair does not work. You'll end up with an empty tag. See: https://stackoverflow.com/questions/2658916/serializing-a-list-of-key-value-pairs-to-xml – Maxwin Jul 05 '17 at 08:56
7

This is waaay late - but I found this question whilst looking for the answer myself, and thought I'd share my eventual answer which was to replace XmlSerializer with a different tool that will serialize everything:

http://www.sharpserializer.com

It worked for me straight out of the box, serializing Dictionaries, and multi-layered custom types, and even generics using interfaces as type arguments. Also has a fully permissive license.

Thank you Pawel Idzikowski!

jv42
  • 8,521
  • 5
  • 40
  • 64
Nich Overend
  • 822
  • 8
  • 16
  • 4
    DataContractSerializer will serialize dictionaries as well, and is now part of the .NET Framework. – Eric J. Mar 16 '12 at 18:11
3

You can use ExtendedXmlSerializer. If you have a class:

public class TestClass
{
    public Dictionary<int, string> Dictionary { get; set; }
}

and create instance of this class:

var obj = new TestClass
{
    Dictionary = new Dictionary<int, string>
    {
        {1, "First"},
        {2, "Second"},
        {3, "Other"},
    }
};

You can serialize this object using ExtendedXmlSerializer:

var serializer = new ConfigurationContainer()
    .UseOptimizedNamespaces() //If you want to have all namespaces in root element
    .Create();

var xml = serializer.Serialize(
    new XmlWriterSettings { Indent = true }, //If you want to formated xml
    obj);

Output xml will look like:

<?xml version="1.0" encoding="utf-8"?>
<TestClass xmlns:sys="https://extendedxmlserializer.github.io/system" xmlns:exs="https://extendedxmlserializer.github.io/v2" xmlns="clr-namespace:ExtendedXmlSerializer.Samples;assembly=ExtendedXmlSerializer.Samples">
  <Dictionary>
    <sys:Item>
      <Key>1</Key>
      <Value>First</Value>
    </sys:Item>
    <sys:Item>
      <Key>2</Key>
      <Value>Second</Value>
    </sys:Item>
    <sys:Item>
      <Key>3</Key>
      <Value>Other</Value>
    </sys:Item>
  </Dictionary>
</TestClass>

You can install ExtendedXmlSerializer from nuget or run the following command:

Install-Package ExtendedXmlSerializer