How to Serialize a Dictionary or Hashtable in C#

   This post kind of doesn't fit in with some of my other posts however, I had this question, and when I searched for answers on this, the answers I found were either incomplete, inneficient or outdated. So to make it easy for everyone, I'm writing this complete and up to date blog post (well as of this date any way!).

   This post was written using .NET Framework 4.0 and storing my data in SQL Server 2008.

   Let's take a look at the problem I had at hand. I needed to be able to store Key\Value pairs from a C# application into SQL. Since I did not know how many key value pairs I might end up with I decided to use the Dictionary object in c#. The problem is, both the Dictionary and Hashtable classes or not serializabe because they implement the IDictionary interface. Here's the error that you will get if you try to serialize one of the classes:

System.NotSupportedException was unhandled
Message=The type System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] is not supported because it implements IDictionary.
Source=System.Xml
StackTrace:
at System.Xml.Serialization.TypeScope.GetDefaultIndexer(Type type, String memberInfo)
at System.Xml.Serialization.TypeScope.ImportTypeDesc(Type type, MemberInfo memberInfo, Boolean directReference)
at System.Xml.Serialization.TypeScope.GetTypeDesc(Type type, MemberInfo source, Boolean directReference, Boolean throwOnError)
...

   The reason the System.NotSupportedException is thrown is because the IDictionary class implements the IXmlSerializable interface.The IXmlSerializable interface makes us overide the following methods: GetSchema, ReadXml and WriteXml. We can do this, but since we have to write a class to overide these functions anyway, it's easier to just write a generic class and use that for serialization. Let's take a look.

   What we are going to do is make a stub class that will be serializbe that mimics the Dictionary or Hashtable DictionaryItem or KeyValuePair<string, string>. We want this class to be a simple a possible:

public class DataItem
{

public string Key;

public string Value;

public DataItem(string key, string value)

{

Key = key;

Value = value;

}

  Now we will use the System.Generics.List  to mimic the dictionary or hashtable classes: 

List<DataItem> tempdataitems = new List<DataItem>(myDictionary.Count);

   Since this is now serializable, we can jjust foreach through our Dictionary or Hashtable objects and build our tempdataitmes class to serialize.

foreach (string key in myDictionary.Keys)

{

tempdataitems.Add(new DataItem(key, myDictionary[key].ToString()));

}

   The last thing I need to do is serialize this to a string so I can now store it in my SQL database with the column type of XML.

private string SerializeJobData()

{

   List<DataItem> tempdataitems = new List<DataItem>(myDictionary.Count);

   foreach (string key in dataitems.Keys)

   {

       tempdataitems.Add(new DataItem(key, dataitems[key].ToString()));

   }

   XmlSerializer serializer = new XmlSerializer(typeof(List<DataItem>));

   StringWriter sw = new StringWriter();

   XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

   ns.Add("","");

   serializer.Serialize(sw, tempdataitems,ns);

   return sw.ToString();

}

   In this example I am using the .net 4 StringWriter class from the System.IO namespace. This makes working with the stream needed for xml serialization simple because it hanldes the stream needed for xml serialization. In addtion you can see that I didn't want the default .net namespace in my xml so I set the namespace of the xmlsericalizer to "". If you want more control over your xml be sure to include your custom namespace.

   Here's what the data looks like in SQL:

<ArrayOfDataItem>

  <DataItem>

    <Key>Vera</Key>

    <Value>Vera</Value>

  </DataItem>

  <DataItem>

    <Key>David</Key>

    <Value>David</Value>

  </DataItem>

  <DataItem>

    <Key>Susan</Key>

    <Value>Susan</Value>

  </DataItem>

  <DataItem>

    <Key>FakeParam</Key>

    <Value>FakeParam</Value>

  </DataItem>

</ArrayOfDataItem> 

   As you can see this is nice and clean.

   The last thing we would need to tacke is deserializing back to a Dictionary<string, string> object. I'm going to again use the StringWriter class to help me.

private void DeserializeData(string RawData)

{

   Dictionary<string, string> myDictionary = new Dictionary<string, string>();

  XmlSerializer xs = new XmlSerializer(typeof(List<DataItem>));

  StringReader sr = new StringReader(RawData);

   List<DataItem> templist = (List<DataItem>)xs.Deserialize(sr);

   foreach (DataItem di in templist)

   {

       myDictionary.Add(di.Key, di.Value);

   }

}

   Super simple!

   I hope this helps you quicly get through this task and answers all questions regarding serializing and deserialize the .net 4 Dictionary and Hashtable classes.