This appendix summarizes useful serialization topics and techniques.
To serialize and deserialize objects in XML format, you use the XmlSerializer
class’s Serialize
and Deserialize
methods. The methods work only for classes that have a parameterless constructor, either the default constructor or one that you created. They also work only for public properties and fields. All other properties and fields are ignored.
To serialize an object, follow these steps.
XmlSerializer
, passing its constructor the object’s type.TextWriter
to hold the serialization.Serialize
method, passing it the TextWriter
and the object to serialize.The following code shows how a program might serialize a Customer
object.
// Create a serializer that works with the Customer class.
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
// Create a TextWriter to hold the serialization.
string serialization;
using (TextWriter writer = new StringWriter())
{
// Serialize the Customer.
serializer.Serialize(writer, customer);
serialization = writer.ToString();
}
// Display the serialization.
serializationTextBox.Text = serialization;
To deserialize a serialization, follow these steps.
XmlSerializer
, passing its constructor the object’s type.TextReader
from which to read the serialization.Deserialize
method, passing it the TextReader
. Cast the result into the object’s type.The following code shows how a program might deserialize a Customer
object’s serialization.
// Create a serializer that works with the Customer class.
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
// Create a stream from which to read the serialization.
using (TextReader reader = new StringReader(serialization))
{
// Deserialize.
Customer newCustomer = (Customer)serializer.Deserialize(reader);
// Display the deserialization.
DisplayCustomer(deserializedTextBox, newCustomer);
}
The following table lists the most useful attributes that you can use to control serialization. (The names of the classes that implement these attributes all end with Attribute
. For example, the first XmlArray
attribute is implemented by the XmlArrayAttribute
class. If you want to look up any of these online, use their full class names.)
Attribute | Purpose |
XmlArray | Changes the name by which the array or list is serialized. |
XmlArrayItem | Indicates a type that can be in an array. For example, suppose the People array contains Person objects, some of which might be from the Author subclass. Then you would use XmlArrayItem twice to indicate that the array might contain Person and Author objects. |
XmlAttribute | Serializes a field as an attribute instead of an element. Optionally sets the name of the attribute. |
XmlElement | Specifically indicates the field will be serialized as an XML element. This attribute allows you to change the XML element’s name. |
XmlEnum | Enables you to specify the names by which enumeration values are serialized. For example, suppose the enumeration MealSize defines values Small , Medium , and Large . You could use this attribute to make the serialization call those values Tall , Grande , and Brobdignagian . |
XmlIgnore | Makes the serializer omit a field from the serialization. |
XmlRoot | Controls the name and namespace for the element generated for a serialization’s root element. For example, the attribute [XmlRoot("Client")] in front of the Customer class would make the serializer name the root element Client . This would not affect Customer objects that are not the root element. (See XmlType .) |
XmlText | Makes the serializer store a value as XML text. An object can have only one text value. (The serializer cannot put more than one text value between the object’s start and end tags.) |
XmlType | Controls the name and namespace for the element generated for a class. For example, if you place the attribute [XmlType("Item")] in front of the OrderItem class, then all OrderItem objects are serialized as Item elements. |
The DataContractSerializer
class can also use XML to serialize and deserialize objects. The process is similar to using the DataContractJsonSerializer
class, which is summarized in the next section.
JavaScript Object Notation (JSON) is a data storage language that mostly consists of name:value pairs where names are text and values can have one of the following data types.
The following section summarizes the basic JSON serialization and deserialization processes. The section after that describes attributes you can use to control the serialization.
The DataContractJsonSerializer
class serializes and deserializes objects using the JSON format. The class’s WriteObject
method serializes an object. Its ReadObject
method deserializes an object.
The following code serializes and deserializes a Customer
object in the JSON format.
// Create a serializer that works with the Customer class.
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(typeof(Customer));
// Create a stream to hold the serialization.
using (MemoryStream stream = new MemoryStream())
{
// Serialize the Customer.
serializer.WriteObject(stream, customer);
// Convert the stream into a string.
stream.Seek(0, SeekOrigin.Begin);
string serialization;
using (StreamReader reader = new StreamReader(stream))
{
serialization = reader.ReadToEnd();
// Display the serialization.
serializationTextBox.Text = serialization;
// Deserialize from the stream.
stream.Position = 0;
Customer newCustomer = (Customer)serializer.ReadObject(stream);
// Display the deserialization.
DisplayCustomer(deserializedTextBox, newCustomer);
}
}
The following table lists attributes that are useful when performing JSON serializations.
Attribute | Purpose |
CollectionDataContract | Allows you to control serialization of collections |
DataContract | Indicates that a type is serializable by a serializer such as a DataContractSerializer |
DataMember | Indicates that a property should be serialized |
EnumMember | Indicates that a property is an enumeration and should be serialized |
IgnoreDataMember | Indicates that a property should not be included in the serialization |
OptionalField | Indicates that a property is optional in a serialization |
The XML and JSON serializers cannot serialize some data types and cannot serialize a data structure that contains reference loops. However, the BinaryFormatter
class can handle both of these issues.
The BinaryFormatter
can work only with classes that are decorated with the Serializable
attribute.
The following code shows how a program might use a BinaryFormatter
to serialize and deserialize a Department
object.
// Create a BinaryFormatter.
IFormatter formatter = new BinaryFormatter();
// Create a stream to hold the serialization.
using (MemoryStream stream = new MemoryStream())
{
// Serialize.
formatter.Serialize(stream, department);
// Display a textual representation of the serialization.
byte[] bytes = stream.ToArray();
string serialization = BitConverter.ToString(bytes).Replace("-", " ");
// Display the serialization.
serializationTextBox.Text = serialization;
// Deserialize.
stream.Seek(0, SeekOrigin.Begin);
Department newDepartment = (Department)formatter.Deserialize(stream);
// Display the new Department's data.
deserializedPictureBox.Image = newDepartment.Logo;
deserializedTextBox.Text = DisplayDepartment(newDepartment);
}
18.118.93.175