Basics of XML Serialization /Deserialization

Standard

XML Serialization
With XML serialization, the public state of objects can be converted into an XML document. Such XML information is often stored on disk to persist data for later use, or is transported over a network or the Internet to send messages between computers.

Serialization Process

In this article I will demonstrate the basics of XML serialization. In the previous 2 articles [Binary Serialization / Deserialization and Serializing/Deserializing Using the SoapFormatter]  binary and soap formatter has been discussed. The System.Xml.dll assembly provides a third formatter System.Xml.Serialization.XmlSerializer. This formatter allows to persist the public state of a given object as pure XML, as opposed to XML data wrapped within a SOAP message and later deserialized back into objects.

The main advantage of XML serialization over binary serialization is portability. XML can be interpreted using many development frameworks and languages, and on computers using a variety of operating systems. This allows to send the XML representation of an object to software applications that are not using the .NET framework or Microsoft Windows. In addition, XML is human-readable and editable, allowing serialized information to be modified using a standard text editor such as Notepad.

There are two key drawbacks of XML serialization.

  • Firstly, only the public state of objects is serialized. Private fields and properties are not represented in the produced XML.
  • Secondly, object references are not maintained when the XML is deserialized into an object; if the original object contained two references to the same object, the deserialization process will generate references to two separate objects.

In the previous 2 articles, I use the MyLuxuryCar sample code which is now also will be used here. The difference is that instead of saving the file in binary or soap file, we will save the object state information in a xml file. For this we need the System.IO namespace. To simplify the code for all of the classes used, following using directives are added to the code file.
using System.IO;
using System.Xml.Serialization;

In the following Main() method SaveObjectAsXmlFormat and DeserializeObjectFromXMLFormat methods are used for serialization and deserialization respectively.
To perform XML serialization on the MyLuxuryCar object, an instance of the XmlSerializer is created.The key difference with the other two (binary and soap) serialization technique is that the XmlSerializer type requires to specify type information that represents the class to serialize. This can be provided as a parameter to the constructor of the XmlSerializer instantiation. Add the following code to create a serializer for the MyLuxuryCar class:

XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType());

Next we need a target for the generated XML. This can be a stream, a TextWriter, an XmlWriter or a subclass of one of these types. In the example code we will serialize to a file using a StreamWriter. Note that the path for the new file is passed into the constructor. Add the below code:

// Save object to a file in XML format.
using(StreamWriter writer = new StreamWriter(fileName))
{
Console.WriteLine("<<<Starting Serializing using XmlSerializer >>>");
xmlFormatter.Serialize(writer, objGraph);
Console.WriteLine(objGraph.ToString());
}

Inside the using snippet, after the stream writer is ready i.e. writer object is created, the XmlSerializer object i.e. xmlFormatter calls the serialize method which accepts two arguments. The first is stream and other one is the object being serialized. The xml file of the persisting object state information will be look like the below:

<?xml version=”1.0″ encoding=”utf-8″?>
<MyLuxuryCar xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
             xmlns:xsd=”http://www.w3.org/2001/XMLSchema”&gt;
  <radio>
    <hasMicrophonePoint>true</hasMicrophonePoint>
    <hasSubwoofers>true</hasSubwoofers>
    <playStations>
      <double>88</double>
      <double>89.6</double>
      <double>100.2</double>
      <double>99.8</double>
    </playStations>
    <stationID>FM-88.9_Radio Foorti</stationID>
  </radio>
  <hasAutomaticWeaponSystem>true</hasAutomaticWeaponSystem>
  <Model>Ferrari</Model>
  <Color>Black</Color>
  <CanJump>true</CanJump>
  <hasWaterProofSystem>true</hasWaterProofSystem>
</MyLuxuryCar>

Deserializing From XML

The deserialization process uses an XmlSerializer object that is created in exactly the same manner as for serialization. To convert the XML from a stream, TextReader or XmlReader to an object, you call the Deserialize method. This method returns a basic object, which can be cast to the appropriate type.
XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType());
using(StreamReader reader = new StreamReader(filename))
{
Console.WriteLine("<<<Starting Deserializing object>>>");
MyLuxuryCar myCar = (MyLuxuryCar)xmlFormatter.Deserialize(reader);
Console.WriteLine(myCar.ToString());
}

Important to note that the XmlSerializer demands that all serialized types in the object graph support a default constructor (so be sure to add it back if any custom constructors are defined). If this is not the case, then an InvalidOperationException will raise at runtime.

The full code snippet is given below:
public class SerializationTest
{
private static void Main(string[] args)
{
string PersistingXMLFileName = "MyLuxuryFerrari.xml";
Car myCar = new MyLuxuryCar(true,true);
myCar.Color = "Black";
myCar.Model = "Ferrari";
myCar.hasAutomaticWeaponSystem = true;
myCar.AddMiles(2000);
myCar.AddCrashes(5);
myCar.radio.hasSubwoofers = true;
myCar.radio.playStations = new double[] {88.0, 89.6, 100.2, 99.8};
myCar.radio.hasMicrophonePoint = true;
// Serialize myCar object.
SaveObjectAsXmlFormat(myCar, PersistingXMLFileName);
// Deserialize myCar object from the XML file
DeserializeObjectFromXMLFormat(myCar, PersistingXMLFileName);
Console.Read();
}
static void SaveObjectAsXmlFormat(object objGraph, string fileName)
{// Save object to a file in XML format.
XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType());
using(StreamWriter writer = new StreamWriter(fileName))
{
Console.WriteLine("<<<Starting Serializing using XmlSerializer >>>");
xmlFormatter.Serialize(writer, objGraph);
Console.WriteLine(objGraph.ToString());
}
}
static void DeserializeObjectFromXMLFormat(object objGraph, string filename)
{
XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType());
using(StreamReader reader = new StreamReader(filename))
{
Console.WriteLine("<<<Starting Deserializing object>>>");
MyLuxuryCar myCar = (MyLuxuryCar)xmlFormatter.Deserialize(reader);
Console.WriteLine(myCar.ToString());
}
}
}
[Serializable]
public class Radio
{
public bool hasMicrophonePoint;
public bool hasSubwoofers;
public double[] playStations;
[NonSerialized]
public string stationID = "FM-88.9_Radio Foorti";
}
[Serializable]
public class Car
{
public Radio radio = new Radio();
public bool hasAutomaticWeaponSystem;
private int crashesNo = 0;
private int RunningMiles = 50;
public string Model { get; set; }
public string Color { get; set; }
public void AddCrashes(int crashes)
{
crashesNo += crashes;
}
public void AddMiles(int miles)
{
RunningMiles += miles;
}
public override string ToString()
{
return String.Format(@"Car Info: Model -> {0}, Color -> {1}, Traveling -> {2}, Crash(es) - > {3},
Weapon System -> {4}", Model, Color, RunningMiles, crashesNo, hasAutomaticWeaponSystem);
}
}
[Serializable]
public class MyLuxuryCar : Car
{
public MyLuxuryCar() { }
public MyLuxuryCar(bool canJump, bool isWaterProof)
{
CanJump = canJump;
hasWaterProofSystem = isWaterProof;
}
public bool CanJump;
public bool hasWaterProofSystem;
}

XML serialization using the .NET framework supports many configuration options that allow the exact structure of the XML to be controlled. However, in this article I  only used the default settings for serialization. In future articles we will see how to customise the process further, including changing the names of the XML attributes and elements that are created and using XML schemas.

Leave a comment