How to make value type nullable using .NET XmlSerializer?

Suppose I have this object:

[Serializable] public class MyClass { public int Age { get; set; } public int MyClassB { get; set; } } [Serializable] public class MyClassB { public int RandomNumber { get; set; } } 

XmlSerializer serializes the object as follows:

 <MyClass> <Age>0</age> <MyClassB> <RandomNumber>4234</RandomNumber> </MyClassB> </MyClass> 

How can I set the Age property to nullable? IE: don't serialize the Age property when it is under 0?

I tried with Nullable, but it serialized my object as follows:

 <MyClass> <Age d5p1:nil="true" /> <MyClassB> <RandomNumber>4234</RandomNumber> </MyClassB> </MyClass> 

After reading the MSDN documentation, I found the following:

You cannot apply the IsNullable property to a member entered as a value type because the value type cannot contain a nullNothingnullptra reference (Nothing in Visual Basic). In addition, you cannot set this property to false for value types with a null value. When such types have a null reference Nullnothingnullptra (Nothing in Visual Basic), they will be serialized by setting xsi: nil to true.

source: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx

I understand that the type of the value cannot be null. The valuetype type is always set to something. Serialization cannot decide whether to serialize it or not based on the current value.

I tried with attributes, but that didn't work. I tried to create an agecontainer object and manipulate its serialization using attributes, but that didn't work.

I really want:

 <MyClass> <MyClassB> <RandomNumber>4234</RandomNumber> </MyClassB> </MyClass> 

When the Age property is less than 0 (zero).




It looks like you have to implement custom serialization.

Yes, this is what I do too, but I would like to leave without him.

In an application, an object is much more complicated, and I don’t want to handle serialization myself.

+25
null c # value-type xml-serialization
Mar 31 '09 at 21:30
source share
6 answers

I just discovered this. XmlSerialier looks for the XXXSpecified boolean property to determine if it should be included. This should solve the problem beautifully.

 [Serializable] public class MyClass { public int Age { get; set; } [XmlIgnore] public bool AgeSpecified { get { return Age >= 0; } } public int MyClassB { get; set; } } [Serializable] public class MyClassB { public int RandomNumber { get; set; } } 

Evidence:

 static string Serialize<T>(T obj) { var serializer = new XmlSerializer(typeof(T)); var builder = new StringBuilder(); using (var writer = new StringWriter(builder)) { serializer.Serialize(writer, obj); return builder.ToString(); } } static void Main(string[] args) { var withoutAge = new MyClass() { Age = -1 }; var withAge = new MyClass() { Age = 20 }; Serialize(withoutAge); // = <MyClass><MyClassB>0</MyClassB></MyClass> Serialize(withAge); // = <MyClass><Age>20</Age><MyClassB>0</MyClassB></MyClass> } 



Change Yes, this is a documentary function. See MSDN Record for XmlSerializer

Another option is to use a special template to create a logical field recognized by the XmlSerializer, and apply XmlIgnoreAttribute to the field. The template is created as the NameSpecified property. For example, if there is a field named "MyFirstName", you will also create a field called "MyFirstNameSpecified", which instructs the XmlSerializer to generate an XML element named "MyFirstName".

+49
Mar 31 '09 at 10:01
source share
β€” -

Extending Samuel's answer and Greg Beech's comment on the case of a boolean property: if the property is of type bool, you cannot write a simple test in the propertySpecified property.

The solution is to use the Nullable <bool> type, then the test in the property Specified is just property.HasValue. eg.

 using System.Xml.Serialization; public class Person { public bool? Employed { get; set; } [XmlIgnore] public bool EmployedSpecified { get { return Employed.HasValue; } } } 

An alternative to using a type with a null value for a numeric property (suggested by Greg Bick) is to set the property value with an invalid default value, for example -1, as follows:

 using System.ComponentModel; using System.Xml.Serialization; public class Person { [DefaultValue(-1)] public int Age { get; set; } [XmlIgnore] public bool AgeSpecified { get { return Age >= 0; } } } 
+13
Dec 11 '09 at 12:13
source share

You can use XmlElementAttribute.IsNullable :

 [Serializable] public class MyClass { [XmlElement(IsNullable = true)] public int? Age { get; set; } public int MyClassB { get; set; } } 
+4
Dec 18 '13 at 7:51
source share

This should help Make Age int? and..

 public bool ShouldSerializeAge() { return Age.HasValue; } 

.. that means adding ShouldSerializeXXX methods to your class!

+2
Mar 31 '09 at 22:03
source share

Forget Nullable ... ShouldSerializeXXX is a pretty nice solution. Here, age will be serialized according to your condition.

 [Serializable] public class MyClass { public int Age { get; set; } public int MyClassB { get; set; } #region Conditional Serialization public bool ShouldSerializeAge() { return age > 0; } #endregion } [Serializable] public class MyClassB { public int RandomNumber { get; set; } } 
0
Nov 12 '09 at 15:02
source share

xsd.exe will auto-generate the XXXSpecified and accessors property if you set the minoccurs attribute as "minoccurs =" 0 "for the element ... if you use a schema to define your xml / class

0
Mar 16 '10 at 3:23
source share



All Articles