Search code examples
c#xml-serializationxmlserializerdefensive-programming

XmlSerializer - How can I set a default when deserializing an enum?


I have a class that looks like this (heavily simplified):

public class Foo
{
    public enum Value
    {
        ValueOne,
        ValueTwo
    }

    [XmlAttribute]
    public Value Bar { get; set; }
}

I'm receiving an XML file from an external source. Their documentation states that the Foo element will only ever have "ValueOne" or "ValueTwo" in the Bar attribute (they don't supply an XSD).

So, I deserialize it like this:

 var serializer = new XmlSerializer(typeof(Foo));
 var xml = "<Foo Bar=\"ValueTwo\" />";
 var reader = new StringReader(xml);

 var foo = (Foo)serializer.Deserialize(reader);

... and that all works.

However, last night, they sent me some XML looking like this instead, and my deserialization failed (as it should):<Foo Bar="" />

Is there a good way to defensively code around this? Ideally I'd like to say something like "default to ValueOne, if something goes wrong here". I don't want to throw away the whole XML file, because a single attribute was mangled.


Solution

  • You can manually parse enum value by creating another property with the same XmlAttribute name:

    public enum Value
    {
        // Default for unknown value
        Unknown,
        ValueOne,
        ValueTwo
    }
    
    [XmlIgnore]
    public Value Bar { get; set; }
    
    [XmlAttribute("Bar")]
    public string _Bar
    {
        get { return this.Bar.ToString(); }
        set { this.Bar = Enum.TryParse(value, out Value enumValue) ? enumValue : Value.Unknown; }
    }
    

    Usage the same as your before

    var serializer = new XmlSerializer(typeof(Foo));
    var xml = "<Foo Bar=\"invalid value\" />";
    var reader = new StringReader(xml);
    var foo = (Foo)serializer.Deserialize(reader);