Can I configure the DataContractSerializer to not create optional (i.e. Nullable<> and List<>) elements in output XML?
Asked Answered
S

2

13

I am using the new .NET 3.0 DataContractSerializer. I have both Nullable<> and List<> objects I am going to serialize. Example:

[DataContract(Namespace = "")]
class Test
{
    public static void Go()
    {
        Test test = new Test();

        var dcs = new DataContractSerializer(typeof(Test));
        dcs.WriteObject(new StreamWriter("test.xml").BaseStream, test);
    }

    [DataMember]
    public Nullable<int> NullableNumber = null;

    [DataMember]
    public int Number = 5;

    [DataMember]
    public List<int> Numbers = new List<int>();
}

When .NET serializes a null or an empty list, it puts in nil (for Nullable) and empty (for lists) elements into the XML. The above example generates:

<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <NullableNumber i:nil="true"/>
  <Number>5</Number>
  <Numbers xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</Test>

For reasons I don't have time to describe I would like to eliminate the superfluous NullableNumber and Numbers elements, like so:

<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Number>5</Number>
</Test>

Indeed, the above file deserializes with the serializer just fine.

Thanks for your help!

Snapp answered 1/4, 2009 at 23:17 Comment(0)
S
25

Mark the field with

   [DataMember(EmitDefaultValue=false)]

That will work for at the least the nullable value type case. For the List case you may need to defer creation of the list until it is needed, or else null the member if it is empty before serialization.

Smyth answered 1/4, 2009 at 23:51 Comment(0)
I
1

I really needed the same thing, but applied globally to lots of fields in generated RIA classes. I'm not sure if this XML is acceptable to DataConstract for deserializing. But it is readable, which suites my purposes...

    public override string ToString()
    {
        var doc = XDocument.Parse(this.ToXML());
        WalkElement(doc.Root);
        return doc.ToString( SaveOptions.None );
    }
    void WalkElement(XElement e)
    {
        var n = e.GetNamespaceOfPrefix("i");
        if (n != null)
        {
            var a = e.Attribute(n + "nil");
            if (a != null && a.Value.ToLower() == "true")
                e.Remove();
        }
        foreach (XElement child in e.Elements().ToList())
            WalkElement(child);
    }
Influence answered 28/3, 2013 at 19:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.