XML Serialization using XmlSerializer in C#


XML Serialization and Serialization in general are explained in Serialization article.

In this article we will explain XML Serialization using XmlSerializer type. We will also discuss about formatting the resulting XML and Serializing Set of objects.

XmlSerializer type defined in System.Xml.Serialization namespace serializes and deserializes an object or group of connected objects in object graph into pure XML data. Serialize method persists object graph to specified stream as XML string and Deserialize method converts XML stream to an object graph.

All the classes in the inheritance hierarchy must be decorated with [Serializable] attribute, in order to serialize the derived class completely. XmlSerializer requires default constructor to Serialize/Deserialize. Compiler removes default constructor if a custom constructor is defined, so you have to add default constructor back to the Type definition.

Below code sample shows Serialize/Deserialize using XmlSerializer.

DerivedClass inherits from BaseClass. BaseClass has Name, id and ID members, DerivedClass has one member Age. In the Main function we create an instance of DervidedClass, change the Name property to John, change ID to 3456 and then persist it to file “Sample.xml” using the Serialize method.  The constructor of the XmlSerializer needs Type of the object to be Serialized/Deserialized as parameter. You have to pass file stream and DerivedClass objects to Serialize method. We then reopen the “Sample.xml” file and Deserialize the persisted stream to DerivedClass object using Deserialize method. Deserialize method takes stream as input and returns object type, you have to type cast and store in DerivedClass reference. “Sample.xml” file is created in the Bin directory of the application.

    [Serializable]
    public class BaseClass
    {
        public string Name = "Jack";

        private string id = "1234";

        public string ID
        {
            get
            {
                return this.id;
            }
            set
            {
                this.id = value;
            }
        }
    }

    [Serializable]
    public class DerivedClass : BaseClass
    {
        public int Age = 22;        
    }
    
    public static void Main()
    {
        // Create a DerivedClass object.
        DerivedClass derivedClassObject = new DerivedClass();

        // Change name from Jack to John
        derivedClassObject.Name = "John";

        // Change ID to 3456
        derivedClassObject.ID = "3456";

        // Create instance of XmlSerializer.
        // You have to pass the Type of the object to be Serialized/Deserialized
        XmlSerializer serializer = new XmlSerializer(typeof(DerivedClass));

        // Create a File stream with write access.
        using (Stream stream = new FileStream("Sample.xml", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            // Serialize the derived class object by using the Serialize Method.
            serializer.Serialize(stream, derivedClassObject);
        }

        // Create an Instance of Derived Class object.
        DerivedClass derivedClassObjectDeserialzed = new DerivedClass();

        // Open the file created during serialization process.
        using (Stream stream = File.OpenRead("Sample.xml"))
        {
            // Deserialze the stream to DerivedClass object.
            derivedClassObjectDeserialzed = serializer.Deserialize(stream) as DerivedClass;
        }

        // Print properties to verify Deserialization process
        // is done properly. Name should be John.
        Console.WriteLine(derivedClassObjectDeserialzed.Name);
        Console.WriteLine(derivedClassObjectDeserialzed.ID);

        // OUTPUT
        // John
        // 3456
    }

Formatting the Output XML

XmlSerializer by default serializes all the public fields and properties as XML elements. System.Xml.Serialization defines attributes like [XmlAttribute], [XmlElement], [XmlText] and many more which are used to decorate the types so that the corresponding field/property is serialized accordingly.

If you decorate the Name field of the BaseClass in the above example with [XmlAttribute], Name is serialized as xml attribute instead of xml element. In the below sample.xml,  Name is serialized as attribute of DerivedClass element.

<?xml version="1.0"?>
<DerivedClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="John">
  <ID>3456</ID>
  <Age>22</Age>
</DerivedClass>
    [Serializable]
    public class BaseClass
    {
        [XmlAttribute]
        public string Name = "Jack";

        private string id = "1234";

        public string ID
        {
            get
            {
                return this.id;
            }
            set
            {
                this.id = value;
            }
        }
    }
    
    [Serializable]
    public class DerivedClass : BaseClass
    {
        public int Age = 22;        
    }

Serializing Set of Objects

Serialize method takes object of type object as input and Deserialize method returns object as return type. As we know by now, Serializers serialize all the contained objects marked with [Serializable] attribute. To serialize a set of objects we can contain the set of objects in one of the Collection types provided in System.Collections or System.Collections.Generic namespace, these collection types are already marked with [Serializable] attribute.

In the below Main method, Generic List of type DerivedClass is initialized with two DerivedClass objects with ID 10 and 20. We persist the collection to Sample.xml file and then recreate the collection using Sample.xml file stream. Contents of persisted Sample.xml file are shown below.

    public static void Main()
    {
        List<DerivedClass> list = new List<DerivedClass>();

        // Add object with ID - 10
        list.Add(new DerivedClass() { ID = "10" });

        // Add object with ID - 20
        list.Add(new DerivedClass() { ID = "20" });

        // Create instance of XmlSerializer.
        // You have to pass the Type of the object to be Serialized/Deserialized
        XmlSerializer serializer = new XmlSerializer(typeof(List<DerivedClass>));

        // Create a File stream with write access.
        using (Stream stream = new FileStream("Sample.xml", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            // Serialize the collection by using the Serialize Method.
            serializer.Serialize(stream, list);
        }

        // Create an Instance of List of type DerivedClass
        List<DerivedClass> listDeserialized = new List<DerivedClass>();

        // Open the file created during serialization process.
        using (Stream stream = File.OpenRead("Sample.xml"))
        {
            // Deserialze the stream to collection.
            listDeserialized = serializer.Deserialize(stream) as List<DerivedClass>;
        }

        // Iterate through the list and Print ID's
        foreach (DerivedClass obj in listDeserialized)
        {
            Console.WriteLine(obj.ID);
        }

        // OUTPUT
        // 10
        // 20
    }

 

<?xml version="1.0"?>
<ArrayOfDerivedClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DerivedClass>
    <Name>Jack</Name>
    <ID>10</ID>
    <Age>22</Age>
  </DerivedClass>
  <DerivedClass>
    <Name>Jack</Name>
    <ID>20</ID>
    <Age>22</Age>
  </DerivedClass>
</ArrayOfDerivedClass>