代码之家  ›  专栏  ›  技术社区  ›  Eric

是否可以将DataContractSerializer配置为不在输出XML中创建可选(即可以为空的<>和列表<>)元素?

  •  13
  • Eric  · 技术社区  · 15 年前

    我正在使用新的.NET 3.0 DataContractSerializer。我有两个可以空的< >和列表& lt; >我要序列化的对象。例子:

    [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>();
    }
    

    当.NET序列化一个空列表或空列表时,它将nil(对于可以为空)和empty(对于列表)元素放入XML中。上面的示例生成:

    <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>
    

    由于我没有时间描述的原因,我想消除多余的nullablenumber和numbers元素,如:

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

    实际上,上面的文件使用序列化程序进行反序列化是很好的。

    谢谢你的帮助!

    2 回复  |  直到 11 年前
        1
  •  24
  •   Darren Clark    15 年前

    在字段上标记

       [DataMember(EmitDefaultValue=false)]
    

    这至少适用于可以为空的值类型的情况。 对于列表案例,您可能需要将列表的创建推迟到需要时为止,或者如果在序列化之前该成员为空,则为空。

        2
  •  1
  •   Gabe Halsmer    11 年前

    我确实需要同样的东西,但是在全球范围内应用于生成的RIA类中的许多字段。我不确定Dataconstract是否接受此XML进行反序列化。但它是可读的,符合我的目的…

        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);
        }