XmlSerializer Class

XmlSerializer makes possible serializing and deserializing object instances into/from XML content. The class contains various overloads to support serializing directly into file or by XElement, XmlWriter, any TextWriter and any Stream implementations.

Definition

Namespace: KGySoft.Serialization.Xml
Assembly: KGySoft.CoreLibraries (in KGySoft.CoreLibraries.dll) Version: 7.0.0
C#
public static class XmlSerializer
Inheritance
Object    XmlSerializer

Remarks

  Security Note

The XmlSerializer supports polymorphism and stores type information whenever the type of a member or collection element differs from the type of the stored instance. If the XML content to deserialize is from an untrusted source make sure to use the DeserializeSafe and DeserializeContentSafe methods to prevent loading assemblies during the deserialization. Please note though that it cannot protect you from all possible threats if a type of the already loaded assemblies can be exploited for a security attack. The XmlSerializer can only create objects by using their default constructor and is able to set the public fields and properties. It can also create collections by special initializer constructors and can populate them by the standard interface implementations.

In safe mode you must preload every assembly that are referred in the XML content. Additionally, in safe mode an InvalidOperationException is thrown for content that is serialized by BinarySerializationFormatter (see the BinarySerializationAsFallback option).

XmlSerializer supports serialization of any simple types and complex objects with their public properties and fields as well as several collection types.

  Note

Unlike the System.Xml.Serialization.XmlSerializer class, this XmlSerializer is not designed for customizing output format (though IXmlSerializable implementations are considered). Not even Xml...Attributes are supported (except XmlRootAttribute for the root element of IXmlSerializable implementations). Instead, this class is designed to support XML serialization of any type as long as they have a default constructor and their state can be fully restored by their public fields and properties.

Several System.ComponentModel techniques are supported, which also makes possible to use the XmlSerializer for types that can be edited in a property grid, such as components, configurations or any types in a custom designer. The supported component model attributes and techniques:

Basically types with default constructors are supported. However, if a field or property value is not after creating its parent object and the type has no parameterless constructor, then the returned instance is tried to be re-used on deserialization.

  Note

Objects without a default constructor can be serialized at root level also by the SerializeContent methods into an already existing XElement node or by an XmlWriter, which already opened and XML element before calling the SerializeContent method. When deserializing, the result object should be created by the caller, and the content can be deserialized by the DeserializeContent methods.

Options:
By specifying the XmlSerializationOptions argument in the Serialize and SerializeContent methods you can override the default behavior of serialization. The default options and the None option ensure that only those types are serialized, which are guaranteed to be able to deserialized perfectly. For details see the description of the None option.

If a type cannot be serialized with the currently used options a SerializationException will be thrown.

You can use RecursiveSerializationAsFallback option to enable recursive serialization of every type of objects and collections. A collection type can be serialized if it implements the ICollectionT, IList or IDictionary interfaces, and it can be deserialized if it has a default constructor, or an initializer constructor with a single parameter that can accept an Array or ListT instance (non-dictionaries) or a DictionaryTKey, TValue instance (dictionary collections). Non-collection types must have a parameterless constructor to be able to be deserialized.

If BinarySerializationAsFallback option is enabled, then types without a native support and appropriate TypeConverter will be serialized into a binary stream, which will be stored in the result XML. Though this provides the best compatibility of any type, it hides the whole inner structure of the serialized object. If a root level object without native support is serialized by the Serialize using the BinarySerializationAsFallback, then the whole XML result will be a single node with the binary content.

See the XmlSerializationOptions enumeration for further options.

New features and improvements compared to System.Xml.Serialization.XmlSerializer:

  • Strings – If a string contains only white spaces, then system XmlSerializer cannot deserialize it properly. String instances containing invalid UTF-16 code points are also cannot be serialized. This XmlSerializer implementation handles them correctly.
  • Collections with base element type – If the element type of a collection is a base type or an interface, then the system serializer throws an exception for derived element types suggesting that XmlIncludeAttribute should be defined for all possible derived types. Unfortunately this attribute is applicable only for possible types of properties/fields but not for collection elements. And in many cases it simply cannot be predefined in advance what derived types will be used at run-time.
  • Collections with read-only properties – Usually collection properties can be read-only. But to be able to use the system serializer we need to define a setter for such properties; otherwise, serialization may fail. This XmlSerializer does not require setter accessor for a collection property if the property is not after initialization and can be populated by using the usual collection interfaces.
  • Objects without default constructors – The system serializer requires that the deserialized types have default constructors. On deserializing fields and properties, this XmlSerializer implementation tries to use the return value of the members. If they are not after creating their container object, then the returned instances will be used instead of creating a new instance.

Example

C#
using System;
using System.IO;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml.Linq;
using KGySoft.CoreLibraries;
using KGySoft.Serialization.Xml;

// A good candidate for XML serialization:
public class Person
{
    public string FirstName { get; set; }

    [DefaultValue(null)] // will not be serialized if null
    public string MiddleName { get; set; }

    public string LastName { get; set; }

    public DateTime BirthDate { get; set; }

    // System serializer fails here: the property has no setter and its type cannot be instantiated.
    public IList<string> PhoneNumbers { get; } = new Collection<string>();
}

public class Program
{
    public static void Main()
    {
        var person = ThreadSafeRandom.Instance.NextObject<Person>();
        var options = XmlSerializationOptions.RecursiveSerializationAsFallback;

        // serializing into XElement
        XElement element = XmlSerializer.Serialize(person, options);
        var clone = (Person)XmlSerializer.Deserialize(element);

        // serializing into file/Stream/TextWriter/XmlWriter are also supported: An XmlWriter will be used
        var sb = new StringBuilder();
        XmlSerializer.Serialize(new StringWriter(sb), person, options);
        clone = (Person)XmlSerializer.Deserialize(new StringReader(sb.ToString()));

        Console.WriteLine(sb);
    }
}

// This code example produces a similar output to this one:
// <?xml version="1.0" encoding="utf-16"?>
// <object type="Person">
//   <FirstName>Uehaccuj</FirstName>
//   <MiddleName>Rnig</MiddleName>
//   <LastName>Iuvmozu</LastName>
//   <BirthDate>1996-06-02T00:00:00Z</BirthDate>
//   <PhoneNumbers type="System.Collections.ObjectModel.Collection`1[System.String]">
//     <item>694677853</item>
//     <item>6344</item>
//   </PhoneNumbers>
// </object>

Methods

Deserialize(Stream) Deserializes an object from the provided Stream in stream parameter.
Deserialize(String) Deserializes an object from the specified file passed in fileName parameter.
Deserialize(TextReader) Deserializes an object using the provided TextReader in reader parameter.
Deserialize(XElement) Deserializes an XML content to an object. Works for the results of the Serialize(Object, XmlSerializationOptions) method.
Deserialize(XmlReader) Deserializes an object using the provided XmlReader in reader parameter.
DeserializeContent(XElement, Object) Restores inner state of an already created object passed in obj parameter based on a saved XML. Works for the results of the SerializeContent(XElement, Object, XmlSerializationOptions) method and other SerializeContent overloads.
DeserializeContent(XmlReader, Object) Restores inner state of an already created object passed in obj parameter based on a saved XML. Works for the results of the SerializeContent(XmlWriter, Object, XmlSerializationOptions) method and other SerializeContent overloads.
DeserializeContentSafe(XElement, Object) Restores inner state of an already created object passed in obj parameter based on a saved XML. Works for the results of the SerializeContent(XElement, Object, XmlSerializationOptions) method and other SerializeContent overloads.
See the security notes at the Remarks section of the XmlSerializer class for details about safe mode.
DeserializeContentSafe(XmlReader, Object) Restores inner state of an already created object passed in obj parameter based on a saved XML. Works for the results of the SerializeContent(XmlWriter, Object, XmlSerializationOptions) method and other SerializeContent overloads.
See the security notes at the Remarks section of the XmlSerializer class for details about safe mode.
DeserializeSafe(Stream) Deserializes an object from the provided Stream in stream parameter.
DeserializeSafe(String) Deserializes an object from the specified file passed in fileName parameter.
See the security notes at the Remarks section of the XmlSerializer class for details about safe mode.
DeserializeSafe(TextReader) Deserializes an object using the provided TextReader in reader parameter.
See the security notes at the Remarks section of the XmlSerializer class for details about safe mode.
DeserializeSafe(XElement) Deserializes an XML content to an object in safe mode. Works for the results of the Serialize(Object, XmlSerializationOptions) method.
See the security notes at the Remarks section of the XmlSerializer class for details about safe mode.
DeserializeSafe(XmlReader) Deserializes an object using the provided XmlReader in reader parameter.
See the security notes at the Remarks section of the XmlSerializer class for details about safe mode.
Serialize(Object, XmlSerializationOptions) Serializes the object passed in obj parameter into a new XElement object.
Serialize(Stream, Object, XmlSerializationOptions) Serializes the object passed in obj into the provided Stream.
Serialize(String, Object, XmlSerializationOptions) Serializes the object passed in obj into the specified fileName.
Serialize(TextWriter, Object, XmlSerializationOptions) Serializes the object passed in obj by the provided TextWriter object.
Serialize(XmlWriter, Object, XmlSerializationOptions) Serializes the object passed in obj by the provided XmlWriter object.
SerializeContent(XElement, Object, XmlSerializationOptions) Saves public properties or collection elements of an object given in obj parameter into an already existing XElement object given in parent parameter with provided options.
SerializeContent(XmlWriter, Object, XmlSerializationOptions) Saves public properties or collection elements of an object given in obj parameter by an already opened XmlWriter object given in writer parameter with provided options.

See Also