1

I would like to know how to ignore a specific item/index of a List<T> from being serialized using XmlSerializer.

For example, consider the following list:

...
List<int> collection = new List<int>() {0, 1, 2};
...

What I would like to achieve is when serializing the above List<int> using XmlSerializer, I want the 0 to be ignored from being serialized, so the desired result is:

...
<collection>
    <int>1</int>
    <int>2</int>
</collection> // as you can see - there is no <int>0</int> value.
...

Thanks.

UPDATE

The following code is a concrete example of my question:

[Serializable]
public class Ball
{
    private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(Ball));

    public Ball()
    {
        // value 1 is a default value which I don't want to be serialized.
        Points = new List<int>() { 1 };
        IsEnabled = false;
    }

    public List<int> Points { get; set; }
    public bool IsEnabled { get; set; }

    public void Save()
    {
        using (StreamWriter writer = new StreamWriter(FILENAME))
        {
            Serializer.Serialize(writer, this);
        }
    }

    public Ball Load()
    {
        using (StreamReader reader = new StreamReader(FILENAME))
        {
             return (Ball)Serializer.Deserialize(reader);
        }
    }
}
Eido95
  • 1,313
  • 1
  • 15
  • 29
  • 4
    Is there any reason you can't simply remove the item from your list before serializing? – David L Nov 18 '15 at 17:30
  • 1
    If you like cheating, Just delete that item/index right before serialization..? – KDecker Nov 18 '15 at 17:30
  • As far as I know there's no equivalent to [`ShouldSerialize`](https://msdn.microsoft.com/en-us/library/53b8022e%28v=vs.110%29.aspx) for individual collection elements - perhaps because it would mess up the collection indexing. You might need to have a [proxy property](https://stackoverflow.com/questions/26575354/stackoverflow-exception-when-serializing-class/26575613#26575613) on your containing class that implements the filter. Can you give a [concrete example](http://stackoverflow.com/help/mcve) of when & how you want to do this? – dbc Nov 18 '15 at 17:39
  • Hey DavidL and KDecker thank you for your answer, I already thought about your advice, but considering the future when I would have a LARGE number of default values (not for the specified, for other lists as well) I THINK it would effect the serialization performance and assign to the heap lots of temporary object that have very temporary usage. – Eido95 Nov 18 '15 at 17:51
  • dbc, I added a concrete example. – Eido95 Nov 18 '15 at 18:05
  • Do you always want to skip the *same* list entries or values for your `Ball` class, or does the set of values to ignore change at runtime? – dbc Nov 18 '15 at 18:07
  • I want to always skip the same list items, they can even be in `List` index 0. The "default values" are set at the constructor. – Eido95 Nov 18 '15 at 18:12
  • Is this an XY problem where you are really trying to solve the problem [Deserializing List with XmlSerializer Causing Extra Items](http://stackoverflow.com/questions/9589589/deserializing-listint-with-xmlserializer-causing-extra-items) without having to move the list initialization out of the constructor? – dbc Nov 18 '15 at 23:25

2 Answers2

3

I suspect you are actually trying to solve an XY problem where the real problem is the one described in the question Deserializing List with XmlSerializer Causing Extra Items: when you serialize and deserialize a collection property that has default items added in the constructor, the default items get duplicated, because the deserialized default items get added to the latest default items.

That answer to that question provides one workaround, namely to move initialization of the default collection entries out of the constructor. If that's not convenient, you can instead introduce a proxy array property and serialize that instead of the underlying collection:

[Serializable]
public class Ball
{
    public Ball()
    {
        Points = new List<int>() { 1 };
        IsEnabled = false;
    }

    public bool IsEnabled { get; set; }

    [XmlIgnore]
    public List<int> Points { get; set; }

    [XmlArray("Points")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public int[] SerializablePoints
    {
        get
        {
            return (Points == null ? null : Points.ToArray());
        }
        set
        {
            Points = ListExtensions.Initialize(Points, value);
        }
    }
}

public static class ListExtensions
{
    public static List<T> Initialize<T>(List<T> list, T[] value)
    {
        if (value == null)
        {
            if (list != null)
                list.Clear();
        }
        else
        {
            (list = list ?? new List<T>(value.Length)).Clear();
            list.AddRange(value);
        }
        return list;
    }
}

For an explanation of why the property must be an array, see XML Deserialization of collection property with code defaults.

Community
  • 1
  • 1
dbc
  • 104,963
  • 20
  • 228
  • 340
2

Better solution is to create a new collection with LINQ query and pass to serializer, like

List<int> collection = new List<int>(){ 0, 1, 2, 3 };
using (var fs = new StreamWriter("serialized.txt"))
{
    XmlSerializer serializer = new XmlSerializer(collection.GetType());
    serializer.Serialize(fs, collection.Where(x => x != 0).ToList());
}
cassandrad
  • 3,412
  • 26
  • 50
  • You cannot serialize an enumerable like that with `XmlSerializer`. In order to serialize an enumerable, it [must implement an `Add(Object)` method](http://www.hanselman.com/blog/YouMustImplementTheAddSystemObjectMethodOnMyClassBecauseItInheritsFromIEnumerable.aspx). – dbc Nov 18 '15 at 18:06
  • @dbc I've clarified example. – cassandrad Nov 18 '15 at 19:40
  • Hey cassandradied thank you for your answer, your answer seems to work when serializing a specific list, however my goal is when I am serializing the **entire** `Ball` class, the "default values" (which are list items) won't be serialized with it. – Eido95 Nov 18 '15 at 21:03