Xml Serialization - Hide Null Values

Xml serialization - Hide null values

You can create a function with the pattern ShouldSerialize{PropertyName} which tells the XmlSerializer if it should serialize the member or not.

For example, if your class property is called MyNullableInt you could have

public bool ShouldSerializeMyNullableInt() 
{
return MyNullableInt.HasValue;
}

Here is a full sample

public class Person
{
public string Name {get;set;}
public int? Age {get;set;}
public bool ShouldSerializeAge()
{
return Age.HasValue;
}
}

Serialized with the following code

Person thePerson = new Person(){Name="Chris"};
XmlSerializer xs = new XmlSerializer(typeof(Person));
StringWriter sw = new StringWriter();
xs.Serialize(sw, thePerson);

Results in the followng XML - Notice there is no Age

<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Chris</Name>
</Person>

Ignore null values - Serialization

With System.Runtime.Serialization.DataContractSerializer you need to mark the property with [DataMember(EmitDefaultValue = false)].

Example, the code below:

class Program
{
static void Main()
{
Console.WriteLine(SerializeToString(new Person { Name = "Alex", Age = 42, NullableId = null }));
}

public static string SerializeToString<T>(T instance)
{
using (var ms = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(ms, instance);
ms.Seek(0, SeekOrigin.Begin);
using (var sr = new StreamReader(ms))
{
return sr.ReadToEnd();
}
}
}
}

[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember(EmitDefaultValue = false)]
public int? NullableId { get; set; }
}

prints the following:

<Person xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication4" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Age>42</Age>
<Name>Alex</Name>
</Person>

How to exclude null properties when using XmlSerializer

I suppose you could create an XmlWriter that filters out all elements with an xsi:nil attribute, and passes all other calls to the underlying true writer.

WebAPI: Null values not suppressed by Default XML Serializer

This declarative tag - [XmlElement(IsNullable = false)] - is honored by the XmlSerializer, but ignored by the DataContractSerializer. If you want to use this tag you need to explicitly select the XmlSerializer. As follows:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services

...

config.Formatters.XmlFormatter.UseXmlSerializer = true;

...

}
}

XML Serializer ignore attribute depends on condition

You will need to wrap your nullable properties to get it work. For example, for your ValueA

public class Class
{
[XmlIgnore]
public decimal? ValueA { get; set; }

[XmlAttribute("ValueA")]
public decimal ValueAUnwrapped
{
//this will only called, when ShouldSerializeValueAUnwrapped return trues, so no NRE here
get => ValueA.Value;
set => ValueA = value;
}

public bool ShouldSerializeValueAUnwrapped() => ValueA.HasValue;
}

This code instructs serializer to serialize ValueAUnwrapped property only when the original ValueA property has value. This is achieved by adding ShouldSerialize<Name>() function which serializer will call for corresponding Name property: https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/defining-default-values-with-the-shouldserialize-and-reset-methods?view=netframeworkdesktop-4.8

You will also need to pereform the same trick for the ValueB.

Suppress Null Value Types from Being Emitted by XmlSerializer

Try adding:

public bool ShouldSerializeAmount() {
return Amount != null;
}

There are a number of patterns recognised by parts of the framework. For info, XmlSerializer also looks for public bool AmountSpecified {get;set;}.

Full example (also switching to decimal):

using System;
using System.Xml.Serialization;

public class Data {
public decimal? Amount { get; set; }
public bool ShouldSerializeAmount() {
return Amount != null;
}
static void Main() {
Data d = new Data();
XmlSerializer ser = new XmlSerializer(d.GetType());
ser.Serialize(Console.Out, d);
Console.WriteLine();
Console.WriteLine();
d.Amount = 123.45M;
ser.Serialize(Console.Out, d);
}
}

More information on ShouldSerialize* on MSDN.



Related Topics



Leave a reply



Submit