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
Assigning Out/Ref Parameters in Moq
How to Load Dll 'Sqlite.Interop.Dll'
Fire and Forget Async Method in ASP.NET MVC
How to Change the Timeout on a .Net Webclient Object
Split String Containing Command-Line Parameters into String[] in C#
How to Change Menu Hover Color
How to Serialize a Dictionary as Part of Its Parent Object Using JSON.Net
Order of Linq Extension Methods Does Not Affect Performance
How to Split a String by a Multi-Character Delimiter in C#
How to Parse Huge JSON File as Stream in JSON.Net
Up, Down, Left and Right Arrow Keys Do Not Trigger Keydown Event
How to Get Text Formatting with Itextsharp
How to Deserialize Xml into List<T>
Ignoring a Class Property in Entity Framework 4.1 Code First
Accessing a Variable from Another Script C#
How to Load an Assembly to Appdomain with All References Recursively