How to XML-serialize a dictionary

Take a look at the following blog post

  • http://blogs.msdn.com/b/psheill/archive/2005/04/09/406823.aspx
  • http://web.archive.org/web/20100703052446/http://blogs.msdn.com/b/psheill/archive/2005/04/09/406823.aspx

and this one (not in english, but the code is useful)

  • http://huseyint.com/2007/12/xml-serializable-generic-dictionary-tipi/

Code sample from: http://web.archive.org/web/20100703052446/http://blogs.msdn.com/b/psheill/archive/2005/04/09/406823.aspx

using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using System;
public static void Serialize(TextWriter writer, IDictionary dictionary)
{
    List<Entry> entries = new List<Entry>(dictionary.Count);
    foreach (object key in dictionary.Keys)
    {
        entries.Add(new Entry(key, dictionary[key]));
    }
    XmlSerializer serializer = new XmlSerializer(typeof(List<Entry>));
    serializer.Serialize(writer, entries);
}
public static void Deserialize(TextReader reader, IDictionary dictionary)
{
    dictionary.Clear();
    XmlSerializer serializer = new XmlSerializer(typeof(List<Entry>));
    List<Entry> list = (List<Entry>)serializer.Deserialize(reader);
    foreach (Entry entry in list)
    {
        dictionary[entry.Key] = entry.Value;
    }
}
public class Entry
{
    public object Key;
    public object Value;
    public Entry()
    {
    }

    public Entry(object key, object value)
    {
        Key = key;
        Value = value;
    }
}

It generates output like the following, when the keys and values are strings.

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Entry>
    <Key xsi:type="xsd:string">MyKey</Key>
    <Value xsi:type="xsd:string">MyValue</Value>  
  </Entry>
  <Entry>    
    <Key xsi:type="xsd:string">MyOtherKey</Key>    
    <Value xsi:type="xsd:string">MyOtherValue</Value>  
  </Entry>
</ArrayOfEntry>

Please try this alternative easy way:

    void Main()
    {
        var model = new Foo() 
        { 
            RealDictionary = new Dictionary<string, int> { {"A", 23}, {"B", 40} } 
        };
        model.RealDictionary.Add("C", 69);
        
        using (var writer = XmlWriter.Create("c:\\test1.xml"))
            (new XmlSerializer(typeof(Foo))).Serialize(writer, model);
    }
    
    [Serializable]
    public class Foo
    {
        [XmlArray(ElementName ="Elements")]
        [XmlArrayItem(ElementName = "Element")]
        public List<KeyValueElement> SerializableDictionary 
        { 
            get { return RealDictionary.Select(x => new KeyValueElement {Key = x.Key, Value = x.Value}).ToList(); } 
            set { RealDictionary = value.ToDictionary(x=> x.Key, x => x.Value); }
        }
    
        [XmlIgnore]
        public Dictionary<string, int> RealDictionary {get;set;}  
    }
    
    [Serializable]
    public class KeyValueElement
    {
        public string Key { get; set; }
        public int Value { get; set; }  
    }

Here the xml result:

    <Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Elements>
            <Element>
                <Key>A</Key><Value>23</Value>
            </Element>
            <Element>
                <Key>B</Key><Value>40</Value>
            </Element>
            <Element>
                <Key>C</Key><Value>69</Value>
            </Element>
        </Elements>
    </Foo>