Formatting XML When Serializing C# Objects

Serializing your custom objects in C# is quite simple, and there are several powerful tools at your disposal for crafting the exact XML object you need. Let’s take a look at a few of the ways we can harness the power of C#’s built-in XmlSerializer.

Setting Up Your Classes

Let’s see how to set up a custom Person object for XML serialization. We can start with a basic outline for our object:

XmlElement

The names of the object properties and XML properties may not always match. Let’s assume that we need Person.FirstName to serialize to <First> and Person.LastName to serialize to <Last>. To achieve this, we need to use the XmlElement attribute.

Now that this attribute has been set up, XmlSerializer will know how to label the FirstName and LastName properties of any Person object it receives. XmlElement also contains an IsNullable property. Let’s assume that Person.Email is nullable and add the appropriate attribute.

We are now able to have a Person with a null value in the Email property and it will still be included in the structure of the XML.

ShouldSerialize

While IsNullable is a quick and easy way to handle nullability, sometimes we may want more granular control over whether to include a property at all. In this case, the ShouldSerialize method will help us out. Let’s assume that if our person is under the age of 18, we don’t want to include <Age> in our XML whatsoever. To accomplish this, we add a ShouldSerializeAge method to our Person class.

With this addition, the <Age> property in our XML will be completely removed if the person is under 18. This method will work with any property, and will be named using the ShouldSerialize[C# Property Name] convention.

XmlText

Now let’s take a look at our custom PhoneNumber. In our C# definition, we have separated the area code from the last seven digits of each phone number, but we assume that our XML should display each phone number as a whole, formatted number. To accomplish this, we can use [XmlIgnore] and [XmlText] in our definition.

Here, the XmlIgnore tells the serializer to not include either of the two properties when serializing. XmlText allows us to set a custom FormattedNumber property, which combines our two values into a single string, which will be serialized as the string value of the entire PhoneNumber object.

XmlSerializer

Now that we have our object set up to be serialized, let’s actually use the built-in C# serializer to get our XML. Setting up a serializer is simple; we just need to provide the serializer with the object type (Person) and use a StringWriter to print our XML results.

Usage Examples

Now that everything is set up, let’s try a few examples that showcase the power of XmlSerializer.

Example 1 (Happy Path)

In our first example, we have a basic Person with no null properties and an age greater than 18.

Using our serializer, we get the following XML:

A few things to note on this first example are the <First> and <Last> tags that we set up using [XmlElement(ElementName)], as well as the PhoneNumber serializing to a single string that combines the two properties of our object.

Example 2 (Email is null)

Now, let’s see what happens when Email is set to null.

Using our serializer, we get the following XML:

Notice how the <Email> property still exists in the XML but contains no value. This is how IsNullable handles null property values.

Example 3 (Age < 18)

For our final example, let’s look at how our ShouldSerializeAge method handles a Person under the age of 18.

Using our serializer, we get the following XML:

Other Serialization Options

These examples show off a few of the many ways to control your object serialization in C#, but I wanted to include two more ways to customize the XML.

Custom Namespaces

As you may have noticed, XmlSerializer includes two xmlns namespaces in the serialized object by default. While this can sometimes be ignored, if your XML needs to match a particular template, you may need to remove or edit these namespaces. To do this, we will add a namespaces parameter when we call Serialize().

IMPORTANT: The following code is “not supported” per Microsoft, but works as intended to clear namespaces.

Setting the namespaces to empty in this way gives us the following XML when using the object from Example 1.

UTF-8 Encoding

XmlSerializer uses UTF-16 encoding by default. To use UTF-8 encoding, we must set up a custom StringWriter.

Combined with our updated namespaces, this gives us clean, UTF-8 encoded XML:

Using these methods, you can more granularly control how your custom objects are serialized into XML. Whether you need to match formatting for a request, store specific data, or simply want to display your object in a more readable fashion, XMLSerializer can help you ensure your data is both accessible and well-structured.

author avatar
Andre Garivay Developer
Born and raised in Lincoln, Andre’s roots in the Cornhusker state run deep. After completing his studies at the Raikes School at the University of Nebraska-Lincoln, he swiftly embarked on a career in software development, ultimately joining Don’t Panic Labs two years later.

Related posts