Xml serialization override for individual elements

Viewed 38

I have a list of objects that contains two items. Each object contain several properties. My problems is that I have to serialize both items into xml but with different attributes for both elements.

I've already tried XmlAttributeOverrides

Example class:

[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
    public class Apple
    {

[System.Xml.Serialization.XmlElementAttribute(DataType="nonNegativeInteger")]
       public int Index{ get; set;}

       [System.Xml.Serialization.XmlAttributeAttribute()]
       public int Size{ get; set;}

       [System.Xml.Serialization.XmlAttributeAttribute()]
       public decimal Weight{ get; set;}
    }

     void Test()
     {
        List<Apple> apples = new List<Apple>
        {
           new Apple {Index = 0, Size = 1},
           new Apple {Index = 1, Weight = 4}
        };
     }

Result after serialization:

<Apple Size=1>
<  Index>0</Index>
</Apple>
<Apple Weight=4>
<  Index>1</Index>
</Apple>
1 Answers

This looks like "conditional serialization"; here I'm using Nullable<T> as the storage for "does this have a value?", and public bool ShouldSerialize*() is a pattern recognized by many serializers to decide what to do:

    private int? _size;
    [XmlAttribute]
    public int Size
    {
        get => _size.GetValueOrDefault();
        set => _size = value;
    }

    public bool ShouldSerializeSize() => _size.HasValue;

    private decimal? _weight;
    [XmlAttribute]
    public decimal Weight
    {
        get => _weight.GetValueOrDefault();
        set => _weight = value;
    }

    public bool ShouldSerializeWeight() => _weight.HasValue;

With this, the serializer basically does (pseudo-code):

if (obj.ShouldSerializeSize()) output.WriteAttribute("Size", obj.Size);
if (obj.ShouldSerializeWeight()) output.WriteAttribute("Weight", obj.Weight);

You could also use other rules like "only serialize if positive", i.e.

[XmlAttribute]
public int Size {get;set;}

public bool ShouldSerializeSize() => Size > 0;
Related