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.

 

 

 

 

 

 


Comments (10)

  1. Anjum Rizwi says:

    Good Solution,

    I was googling for simple solution finally got.

    Now I am trying to implement.

    Thank you for sharing.

  2. Anjum Rizwi says:

    Example is missing. You must have created a sample.

    Plz share

    anjumrizwi@gmail.com

  3. Syed says:

    make sure to add a parameterless constuctor to the dataitem class

    else it wont compile (not shown in code above)

  4. jimasp says:

    you could alternatively use a keyedcollection.

  5. Limited_Atonement says:

    So to make the question and answer short: How do I serialize a dictionary or hashtable?  Answer: Make your own serializable dictionary or hash table.  There must be a better way…

  6. surbhi says:

    Hi, I tried serializing my dictionary your way.

    I am having string and list as KeyValuePair<string,list>. When i am seriailizing, the <key>…</key>

    <value>…</value> nodes are not coming.

    Some steps are missing with your code or i am misleading somewhere. Can someone please help it on?

  7. The man who knows says:

    This is simple and brilliant. Far better than creating a serializable dictionary that implements IXmlSerializable

  8. Rey says:

    Worked like a charm! this is amazing.. .thank you

  9. Humble says:

    What is working like a charm? The code is not complete. Couple of people said that already. If you care please share the complete code.

  10. MM says:

    Simple, but very effective idea to serialize the class having Dictionary types!

Skip to main content