Workaround to deserialize ‘True’, ‘False’ using XmlSerializer

This is the scenario, system A is taking an xml from system B. System A will deserialize the xml into an object. Unfortunately, a dev in system B decides that System.Xml namespace is evil and construct the xml using StringBuilder. In one of the element, the dev call ToString() method of a boolean variable. The result? the xml contains ‘True’ or ‘False’. System A takes the input and it throws exceptions with error message “The string 'False' is not a valid Boolean value”, or “The string 'True' is not a valid Boolean value'”.

W3C defines boolean data type as ‘true’, ‘false’, ‘0’, and ‘1’. So this behavior is expected.

There is a way to workaround this, only under this scenario, you want to keep the type safety of your object, and you have the code. The steps are:

  • Decorate the boolean property with XmlIgnore.
  • Inherit your class and add a string property, decorate it with XmlElement. Set the element name to match the xml node name.
  • Add code on the new property on the descendant class, to make the property in the descendant class work as an adapter for the actual boolean property.
 [XmlRoot(ElementName = "data", Namespace = "https://contoso.com/")]
[XmlInclude(typeof(MyClassXmlAdapter))]
public class MyClass
{
    [XmlIgnore]
    public bool BooleanField { get; set; }
}

[XmlRoot(ElementName = "data", Namespace = "https://contoso.com/")]
public sealed class MyClassXmlAdapter : MyClass
{
    [XmlElement(ElementName = "Test")]
    public string BooleanAsString
    {
        get
        {
            return XmlConvert.ToString(BooleanField);
        }

        set
        {
            bool ParsedValue;

            if (!Boolean.TryParse(value, out ParsedValue))
                ParsedValue = XmlConvert.ToBoolean(value);

            BooleanField = ParsedValue;
        }
    }
}

In your serialization code, create the XmlSerializer using MyClassXmlAdapter as type, and the serializer will serialize and deserialize to MyClass with no problem. All of your code that works with MyClass won’t have to be changed.

If you don’t have access to the code, or the class is sealed, it is much more difficult. The only way to do it is by using a helper class. In this sample below, MyClass is sealed and you have only the assembly. Then the solution is to create another class that have almost identical fields with MyClass, with the exception the boolean field.

 [XmlRoot(ElementName = "data", Namespace = "https://contoso.com/")]
public sealed class MyClass
{
    [XmlElement]
    public bool BooleanField { get; set; }
}

[XmlRoot(ElementName = "data", Namespace = "https://contoso.com/")]
public sealed class MyClassXmlAdapter
{
    private bool _BooleanField;

    [XmlElement(ElementName = "Test")]
    public string BooleanAsString
    {
        get
        {
            return XmlConvert.ToString(_BooleanField);
        }

        set
        {
            bool ParsedValue;

            if (!Boolean.TryParse(value, out ParsedValue))
                ParsedValue = XmlConvert.ToBoolean(value);

            _BooleanField = ParsedValue;
        }
    }

    public void CopyTo(MyClass target)
    {
        target.BooleanField = this.BooleanField;
    }
}

After deserializing the xml with ‘True’ or ‘False’, call CopyTo().

These solutions are not ideal, but at least, these are better options rather than cleaning up the Xml.