XML serialization is part of .NET since the 1.0 release. It uses attributes and under the hood reflection to serialize data into the XML (https://en.wikipedia.org/wiki/XML) format. To use XML serialization you must reference the System.Xml.Serialization
namespace. Warning: The XmlSerializer class does not serializes objects that are marked as [Obsolete]
.
Important attributes and their hierarchy for XML serialization:
-
XmlArray:
Specifies that the XmlSerializer must serialize a particular class member as an array of XML elements.
-
XmlArrayItem:
Represents an attribute that specifies the derived types that the XmlSerializer can place in a serialized array.
-
XmlAttribute:
Specifies that the XmlSerializer must serialize the class member as an XML attribute.
-
XmlElement:
Indicates that a public field or property represents an XML element when the XmlSerializer serializes or deserializes the object that contains it.
-
XmlEnum:
Controls how the XmlSerializer serializes an enumeration member.
-
XmlIgnore:
Instructs the Serialize(TextWriter, Object) method of the XmlSerializer not to serialize the public field or public read/write property value.
-
XmlRoot:
Controls XML serialization of the attribute target as an XML root element.
-
XmlTextAttribute:
Indicates to the XmlSerializer that the member must be treated as XML text when the class that contains it is serialized or de-serialized.
Object model that will be serialized:
[XmlType(Namespace = "myxmlNamespace", TypeName = "SerializedTypeName")]
[XmlRoot(ElementName = "rootName")]
public class ClassToSerialize
{
[XmlAttribute(AttributeName = "attribute")]
public string MyAttribute { get; set; }
//This value will be ignored
[XmlIgnore]
public int Ignored { get; set; }
[XmlElement(ElementName = "subElement")]
public SubClass SubClass { get; set; }
[XmlArray(ElementName = "array")]
[XmlArrayItem(ElementName = "item1", Type = typeof(Item1))]
[XmlArrayItem(ElementName = "item2", Type = typeof(Item2))]
public BaseItem[] Array { get; set; }
}
//An enum with custom values
public enum TestEnum
{
[XmlEnum(Name = "FirstValue")]
First,
[XmlEnum(Name = "SecondValue")]
Second
}
//A sub class, that is part of the root class that needs to be serialized
//NOTE: Complex types, like this, needs to be serialized as XML elements
//It is not possible to serialize these as attributes
public class SubClass
{
[XmlText]
public string Text { get; set; }
}
//An abstract class, that will be used in an array
public abstract class BaseItem
{
[XmlAttribute(AttributeName = "BaseString")]
public string Value { get; set; }
}
//A derived type
public class Item1 : BaseItem
{
[XmlAttribute(AttributeName = "Item1Double")]
public double DoubleValue { get; set; }
}
//Another derived type
public class Item2 : BaseItem
{
[XmlAttribute(AttributeName = "Item2Int")]
public int IntValue { get; set; }
}
Note: The types that will be serialied must have public
accessibility modifier.
Serialization code:
var data = new ClassToSerialize()
{
Ignored = 42,
MyAttribute = "attribute value",
SubClass = new SubClass
{
Text = "xml text"
},
Array = new BaseItem[]
{
new Item1
{
Value = "Item1 Value",
DoubleValue = 42.42
},
new Item2
{
IntValue = 1242,
Value = "Item2 Value"
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(ClassToSerialize), "namespaceName");
using (var stream = File.Create("testfile.xml"))
{
serializer.Serialize(stream, data);
}
Result XML:
<?xml version="1.0" encoding="utf-8"?>
<rootName
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
attribute="attribute value"
xmlns="namespaceName">
<subElement xmlns="myxmlNamespace">xml text</subElement>
<array xmlns="myxmlNamespace">
<item1
BaseString="Item1 Value"
Item1Double="42.42" />
<item2
BaseString="Item2 Value"
Item2Int="1242" />
</array>
</rootName>
The System.Text.Json
serializer was introduced in .NET Core 3.0 as a NuGet package and it's inlcuded in .NET 5 and later releases by default. It's designed to be an efficient replacement for Newtonsoft.Json
.
Basic usage:
public class Person
{
public string Name { get; init; }
public int Age { get; init; }
}
var person = new Person
{
Name = "test",
Age = 30,
}
string jsonString = JsonSerializer.Serialize(person);
//deserialization:
Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
Serialization and de serialization options can be controlled via the JsonSerializerOptions
class. Important properties:
-
bool AllowTrailingCommas
:Get or sets a value that indicates whether an extra comma at the end of a list of JSON values in an object or array is allowed (and ignored) within the JSON payload being de-serialized.
-
bool WriteIndented
:Gets or sets a value that indicates whether JSON should use pretty printing. By default, JSON is serialized without any extra white space.
-
bool PropertyNameCaseInsensitive
:Gets or sets a value that indicates whether a property's name uses a case-insensitive comparison during deserialization. The default value is false.
-
JsonNamingPolicy? PropertyNamingPolicy
:Gets or sets a value that specifies the policy used to convert a property's name on an object to another format, such as camel-casing, or null to leave property names unchanged.
Possible built-in values, that can be set:
JsonNamingPolicy.CamelCase
-propertyName
JsonNamingPolicy.KebabCaseLower
-property-name
JsonNamingPolicy.KebabCaseUpper
-PROPERTY-NAME
JsonNamingPolicy.SnakeCaseLower
-property_name
JsonNamingPolicy.SnakeCaseUpper
-PROPERTY_NAME
Custom values can be set, by implementing the
JsonNamingPolicy
class. -
bool IncludeFields
:Gets or sets a value that indicates whether fields are handled during serialization and de-serialization. The default value is false.
-
bool IgnoreReadOnlyProperties
:Gets or sets a value that indicates whether null values are ignored during serialization and de-serialization. The default value is false.
-
JsonCommentHandling ReadCommentHandling
:Gets or sets a value that defines how comments are handled during de-serialization.
Possible values:
-
JsonCommentHandling.Disallow
Doesn't allow comments within the JSON input. Comments are treated as invalid JSON if found, and a
System.Text.Json.JsonException
is thrown. This is the default value. -
JsonCommentHandling.Skip
Allows comments within the JSON input and ignores them. The
System.Text.Json.Utf8JsonReader
behaves as if no comments are present. -
JsonCommentHandling.Allow
Allows comments within the JSON input and treats them as valid tokens. While reading, the caller can access the comment values.
-
-
JsonNumberHandling NumberHandling
:Gets or sets an object that specifies how number types should be handled when serializing or de-serializing.
Possible values:
-
JsonNumberHandling.Strict
Numbers will only be read from System.Text.Json.JsonTokenType.Number tokens and will only be written as JSON numbers (without quotes).
-
JsonNumberHandling.AllowReadingFromString
Numbers can be read from System.Text.Json.JsonTokenType.String tokens. Does not prevent numbers from being read from System.Text.Json.JsonTokenType.Number token.
-
JsonNumberHandling.WriteAsString
Numbers will be written as JSON strings (with quotes), not as JSON numbers.
-
JsonNumberHandling.AllowNamedFloatingPointLiterals
The
NaN
,Infinity
and-Infinity
System.Text.Json.JsonTokenType.String
tokens can be read as floating-point constants, and theSystem.Single
andSystem.Double
values for these constants will be written as their corresponding JSON string representations.
-
-
JsonIgnoreCondition DefaultIgnoreCondition
:Gets or sets a value that determines when properties with default values are ignored during serialization or de-serialization. The default value is
JsonIgnoreCondition.Never
.Possible values:
-
JsonIgnoreCondition.Never
Property is always serialized and de-serialized, regardless of IgnoreNullValues configuration.
-
JsonIgnoreCondition.Always
Property is always ignored.
-
JsonIgnoreCondition.WhenWritingDefault
Property is ignored only if it equals the default value for its type.
-
JsonIgnoreCondition.WhenWritingNull
Property is ignored if its value is null. This is applied only to reference-type properties and fields.
-
You can convert complex types into JSON representation, by implementing the JsonConverter<T>
abstract class and then adding the converter to the Converters
collection of your JsonSerializerOptions
instance.
An example converter:
public class CultureInfoConverter : JsonConverter<CultureInfo>
{
public override CultureInfo? Read(ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
return new CultureInfo(reader.GetString()!);
}
public override void Write(Utf8JsonWriter writer,
CultureInfo value,
JsonSerializerOptions options)
{
writer.WriteStringValue(value.Name);
}
}