[ACCEPTED]-How to make a value type nullable with .NET XmlSerializer?-value-type

Accepted answer
Score: 58

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

[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; }
}

Proof:

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>
}

Edit: Yes, it 9 is a documented feature. See the MSDN entry for XmlSerializer

Another 8 option is to use a special pattern to create 7 a Boolean field recognized by the XmlSerializer, and 6 to apply the XmlIgnoreAttribute to the field. The 5 pattern is created in the form of propertyNameSpecified. For 4 example, if there is a field named "MyFirstName" you 3 would also create a field named "MyFirstNameSpecified" that 2 instructs the XmlSerializer whether to generate 1 the XML element named "MyFirstName".

Score: 13

Extending Samuel's answer and Greg Beech's 10 comment to the case of a boolean property: if 9 the property is of type bool then you can't 8 write a simple test in the propertySpecified 7 property.

A solution is to use a Nullable<bool> type, then 6 the test in the propertySpecified property 5 is simply property.HasValue. e.g.

using System.Xml.Serialization;

public class Person
{
    public bool? Employed { get; set; }

    [XmlIgnore]
    public bool EmployedSpecified { get { return Employed.HasValue; } }
}

An alternative 4 to using a nullable type for a numeric property 3 (suggested by Greg Beech) is to set the 2 value property to an invalid default value, such 1 as -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; } }
}
Score: 7

You can use XmlElementAttribute.IsNullable:

[Serializable]
public class MyClass
{
    [XmlElement(IsNullable = true)]
    public int? Age { get; set; }

    public int MyClassB { get; set; }
}

0

Score: 3

This should help Make Age int? and..

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

..it does 2 mean adding the ShouldSerializeXXX methods 1 to your class!

Score: 1

You need to do custom XML serialization; see 1 IXmlSerializer.

public class MyClass : IXmlSerializable
{
    public int Age { get; set; }
    public MyClassB MyClassB { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        // http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        if (reader.IsStartElement("Age"))
            Age = reader.ReadContentAsInt();

        var serializer = new XmlSerializer(typeof(MyClassB));
        MyClassB = (MyClassB)serializer.Deserialize(reader);
    }

    public void WriteXml(XmlWriter writer)
    {
        if (Age > 0)
        {
            writer.WriteStartElement("Age");
            writer.WriteValue(Age);
            writer.WriteEndElement();
        }

        var serializer = new XmlSerializer(typeof(MyClassB));
        serializer.Serialize(writer, MyClassB);
    }
}
Score: 0

Forget about Nullable ... ShouldSerializeXXX 2 is a pretty solution. Here Age will be serialized 1 upon 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; }
}
Score: 0

xsd.exe will autogenerate the XXXSpecified 3 property and accessors if you set the 'minoccurs' attribute 2 as 'minoccurs="0"' for an element ... if 1 you are using a schema to define your xml/class

More Related questions