Serialization is the process of transforming an in-memory object or object graph into a stream of bytes or text. Deserialization is the opposite. .NET classes that support serialization can be found in the System.Runtime.Serialization and System.Xml.Serialization namespaces.
Two the most popular .NET serialization technologies are:
.NET serialization mechanisms:
Mechanism | Output | Serialized members | Class attribute |
---|---|---|---|
DataContractSerializer | XML or JSON | public and private | [DataContract], [DataMember] |
XmlSerializer | XML | public only | [Serializable] |
BinaryFormatter | binary | public and private | [Serializable] |
Example: Serialize and deserialize an instance of a Person class using DataContractSerializer:
using System.IO; using System.Runtime.Serialization; ... static void Main(string[] args) { Person p = new Person { Name = "Leopold Makuta" }; DataContractSerializer ser = new DataContractSerializer(typeof(Person)); // Serialize using (Stream stream = new FileStream("data.xml", FileMode.Create)) { ser.WriteObject(stream, p); } // Deserialize using (Stream stream = new FileStream("data.xml", FileMode.Open)) { Person result = (Person)ser.ReadObject(stream); } } ... [DataContract] public class Person { [DataMember] private Guid ID { get; set; } [DataMember] public string Name { get; set; } public Person() { ID = Guid.NewGuid(); } }
Example: Serialize and deserialize an instance of a Person class using DataContractJsonSerializer:
using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; ... static void Main(string[] args) { Person p = new Person { Name = "Leopold Makuta" }; DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person)); using (MemoryStream stream = new MemoryStream()) { // Serialize ser.WriteObject(stream, p); stream.Position = 0; StreamReader reader = new StreamReader(stream); Console.WriteLine(reader.ReadToEnd()); // displays: {"ID":"4740087d-2bca-491e-a668-4acf5c731cbd","Name":"Leopold Makuta"} // Deserialize stream.Position = 0; Person result = (Person)ser.ReadObject(stream); } } ... [DataContract] public class Person { [DataMember] private Guid ID { get; set; } [DataMember] public string Name { get; set; } public Person() { ID = Guid.NewGuid(); } }
Example: Serialize and deserialize nested collections using DataContractJsonSerializer:
using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; ... static void Main(string[] args) { var countries = new List<Country>() { new Country { Name = "Canada", Provinces = new List<Province>() { new Province { Name = "Quebec", Cities = new List<City>() { new City { Name = "Montreal", Area = 431, Population = 1704694 } } } } } }; DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(List<Country>)); using (MemoryStream stream = new MemoryStream()) { // Serialize ser.WriteObject(stream, countries); stream.Position = 0; StreamReader reader = new StreamReader(stream); Console.WriteLine(reader.ReadToEnd()); // displays: [{"Name":"Canada","Provinces":[{"Cities": // [{"Area":431,"Name":"Montreal","Population":1704694}],"Name":"Quebec"}]}] // Deserialize stream.Position = 0; List<Country> result = (List<Country>)ser.ReadObject(stream); } } ... [DataContract] public class Country { [DataMember] public string Name { get; set; } [DataMember] public List<Province> Provinces { get; set; } } [DataContract] public class Province { [DataMember] public string Name { get; set; } [DataMember] public List<City> Cities { get; set; } } [DataContract] public class City { [DataMember] public string Name { get; set; } [DataMember] public int Area { get; set; } [DataMember] public int Population { get; set; } }
Example: A generic method to deserialize an XML string to an object:
public T FromXml<T>(string xml) { XmlSerializer serializer = new XmlSerializer(typeof(T)); T value; using (StringReader reader = new StringReader(xml)) { object deserialized = serializer.Deserialize(reader); value = (T)deserialized; } return value; } // Usage IEnumerable<Book> list = FromXml<List<Book>>(xml);
Example: A generic method to serialize an object to an XML string:
public string ToXml<T>(T value) { XmlSerializer serializer = new XmlSerializer(typeof(T)); StringBuilder sb = new StringBuilder(); XmlWriterSettings settings = new XmlWriterSettings() { Indent = true, OmitXmlDeclaration = true, }; using (XmlWriter writer = XmlWriter.Create(sb, settings)) { serializer.Serialize(writer, value); } return sb.ToString(); } // Usage List<Book> books = GetBooks(); string xml = ToXml<List<Book>>(books);
Example: Serialize and deserialize an instance of a Person class using XmlSerializer:
using System.IO; using System.Xml.Serialization; ... static void Main(string[] args) { Person p = new Person { Name = "Leopold Makuta" }; // Serialize. string xml; XmlSerializer ser = new XmlSerializer(typeof(Person)); using (StringWriter writer = new StringWriter()) { ser.Serialize(writer, p); xml = writer.ToString(); } // Deserialize. using (StringReader reader = new StringReader(xml)) { Person p2 = (Person)ser.Deserialize(reader); // p2.ID != p.ID // ... } } ... [Serializable] public class Person { private Guid ID { get; set; } // private fields are not serialized public string Name { get; set; } // The default ctor is required for XMLSerializer. public Person() { ID = Guid.NewGuid(); } }
Example: Serialize a collection of book objects using XmlSerializer:
using System.Collections.Generic; using System.IO; using System.Xml.Serialization; ... static void Main(string[] args2) { List<Book> books = new List<Book>(); books.Add(new Book { ID = 1, Title = "Modern C++" }); books.Add(new Book { ID = 2, Title = "DirectX in 7 Days" }); books.Add(new Book { ID = 3, Title = "Programming in Java" }); Library library = new Library(); library.Books = books; XmlSerializer serializer = new XmlSerializer(typeof(Library)); using (StreamWriter writer = new StreamWriter("books.xml")) { serializer.Serialize(writer, library); } } ... public class Book { [XmlAttribute] public int ID { get; set; } [XmlElement("Name")] public string Title { get; set; } [XmlIgnore] public Book isKindle { get; set; } } public class Library { [XmlArray("Items")] [XmlArrayItem("Item")] public List<Book> Books { get; set; } }
Output (books.xml):
<?xml version="1.0" encoding="utf-8"?> <Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Items> <Item ID="1"> <Name>Modern C++</Name> </Item> <Item ID="2"> <Name>DirectX in 7 Days</Name> </Item> <Item ID="3"> <Name>Programming in Java</Name> </Item> </Items> </Library>
Example: Deserialize from a string containing XML to an object using XmlSerializer:
using System.IO; using System.Xml.Serialization; ... public static void Main() { string xml = @"<?xml version=""1.0"" encoding=""utf-8""?> <Person xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""> <FirstName>Leon</FirstName> <LastName>McBeret</LastName> </Person>"; XmlSerializer ser = new XmlSerializer(typeof(Person)); Person p = (Person)ser.Deserialize(new StringReader(xml)); // ... } ... public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
Example: Serialize and deserialize an instance of a Person class using BinaryFormatter:
using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; ... static void Main(string[] args) { Person p = new Person { Name = "Leopold Makuta" }; IFormatter formatter = new BinaryFormatter(); // Serialize. using (Stream stream = new FileStream("data.bin", FileMode.Create)) { formatter.Serialize(stream, p); } // Deserialize. using (Stream stream = new FileStream("data.bin", FileMode.Open)) { Person p2 = (Person)formatter.Deserialize(stream); // ... } // Compress and serialize. using (Stream s = File.Create("data.bin")) // FileStream using (GZipStream ds = new GZipStream(s, CompressionMode.Compress)) formatter.Serialize(ds, person); // Decompress and deserialize. using (Stream s = File.OpenRead("data.bin")) // FileStream using (GZipStream ds = new GZipStream(s, CompressionMode.Decompress)) { Book book2 = formatter.Deserialize(ds) as Book; } } ... [Serializable] public class Person { private Guid ID { get; set; } public string Name { get; set; } public Person() { ID = Guid.NewGuid(); } }
Example: Serialize and deserialize an instance of a Person class using SoapFormatter:
using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Soap; ... static void Main(string[] args) { Person p = new Person { Name = "Leopold Makuta" }; IFormatter formatter = new SoapFormatter(); // Serialize. using (Stream stream = new FileStream("data.xml", FileMode.Create)) { formatter.Serialize(stream, p); } // Deserialize. using (Stream stream = new FileStream("data.xml", FileMode.Open)) { Person p2 = (Person)formatter.Deserialize(stream); // ... } } ... [Serializable] public class Person { private Guid ID { get; set; } public string Name { get; set; } public Person() { ID = Guid.NewGuid(); } }
Example: An example of a class implementing the ISerializable interface:
using System.Runtime.Serialization; using System.Security.Permissions; // SecurityPermission ... [Serializable] public class Person : ISerializable { public int ID { get; set; } public string Name { get; set; } private bool isUpdated = false; public Person() { } protected Person(SerializationInfo info, StreamingContext context) { // Here we could implement security checks to make sure // nobody tampered with data. ID = info.GetInt32("Value1"); Name = info.GetString("Value2"); isUpdated = info.GetBoolean("Value3"); } [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("Value1", ID); info.AddValue("Value2", Name); info.AddValue("Value3", isUpdated); } }