matteeyah
matteeyah

Reputation: 875

Ignore null values - Serialization

How can I set up the System.Runtime.Serialization serializer to ignore null values?

Or do I have to use the XmlSerializer for that? If so, how?

(I don't want <ecommerceflags i:nil="true"/> tags like this to be written, if it's null then just skip it)

Upvotes: 2

Views: 8602

Answers (3)

alex.b
alex.b

Reputation: 4567

With System.Runtime.Serialization.DataContractSerializer you need to mark the property with [DataMember(EmitDefaultValue = false)].

Example, the code below:

class Program
{
    static void Main()
    {
        Console.WriteLine(SerializeToString(new Person { Name = "Alex", Age = 42, NullableId = null }));
    }

    public static string SerializeToString<T>(T instance)
    {
        using (var ms = new MemoryStream())
        {
            var serializer = new DataContractSerializer(typeof(T));
            serializer.WriteObject(ms, instance);
            ms.Seek(0, SeekOrigin.Begin);
            using (var sr = new StreamReader(ms))
            {
                return sr.ReadToEnd();
            }
        }
    }
}

[DataContract]
public class Person
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public int Age { get; set; }
    [DataMember(EmitDefaultValue = false)]
    public int? NullableId { get; set; }
}

prints the following:

<Person xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication4" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Age>42</Age>
  <Name>Alex</Name>
</Person>

Upvotes: 6

Hexo
Hexo

Reputation: 528

As far as I read, you could use the Specified-Feature

public int? Value { get; set; }

[System.Xml.Serialization.XmlIgnore]
public bool ValueSpecified { get { return this.Value != null; } }

To only write it if it's specified.

Another way would be

[System.Xml.Serialization.XmlIgnore]
private int? value;

public int Value { get { value.GetValueOrDefault(); } }

Upvotes: 1

Gy&#246;rgy Kőszeg
Gy&#246;rgy Kőszeg

Reputation: 18013

Though it has less value (except that it makes the serialized stream shorter), you can customize your serialization to achieve this.

When using System.Runtime.Serialization, you can implement the ISerializable interface:

[Serializable]
public class MyClass: ISerializable
{
    private string stringField;
    private object objectField;

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (stringField != null)
            info.AddValue("str", stringField);

        if (objectField != null)
            info.AddValue("obj", objectField);
    }

    // the special constructor for deserializing
    private MyClass(SerializationInfo info, StreamingContext context)
    {
        foreach (SerializationEntry entry in info)
        {
            switch (entry.Name)
            {
                case "str":
                    stringField = (string)entry.Value;
                    break;
                case "obj":
                    objectField = entry.Value;
                    break;
            }
        }
    }
}

When using XML serialization, you can implement the IXmlSerializable interface to customize the output in a similar way.

Upvotes: 0

Related Questions