【问题标题】:XML deserializing null properties to zero and falseXML 将空属性反序列化为零和假
【发布时间】:2012-10-26 10:28:23
【问题描述】:

我正在向解串器传递一个缺少某些属性的 xml 文档。我需要在结果对象中将缺失值设为 null,但当前 ints 反序列化为零并且布尔值设为 false。

下面的示例显示了一个正确反序列化 vals 的文档,但没有 vals 的文档返回零和空值。

如何强制反序列化器不要像这样处理缺失的属性。

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace SOQuestion
{
    class Program
    {
        static void Main(string[] args)
        {

            var resultWithVals = getObject(docWithVals());
            var resultWithoutVals = getObject(docWithoutVals());

            Console.WriteLine("WITH VALS");
            Console.WriteLine(resultWithVals.someBool);
            Console.WriteLine(resultWithVals.someFloat);
            Console.WriteLine(resultWithVals.someInt);
            Console.WriteLine(resultWithVals.someString);


            Console.WriteLine("WITHOUT VALS"); // nulls are returned here as zero and false
            Console.WriteLine(resultWithoutVals.someBool);
            Console.WriteLine(resultWithoutVals.someFloat);
            Console.WriteLine(resultWithoutVals.someInt);
            Console.WriteLine(resultWithoutVals.someString);

            Console.ReadLine();


        }

        public static XmlDocument docWithVals()
        {
            var doc = new XmlDocument();
            var el = (XmlElement)doc.AppendChild(doc.CreateElement("Result"));
            el.SetAttribute("someString", "Hello World");
            el.SetAttribute("someBool", "true");
            el.SetAttribute("someInt", "1");
            el.SetAttribute("someFloat", "1.1");
            return doc;

        }

        public static XmlDocument docWithoutVals()
        {
            var doc = new XmlDocument();
            var el = (XmlElement)doc.AppendChild(doc.CreateElement("Result"));
            el.SetAttribute("someString", "Hello World");
            return doc;

        }


        public static Result getObject(XmlDocument doc)
        {

                var mySerializer = new XmlSerializer(new Result().GetType());
                var myStream = new MemoryStream();
                doc.Save(myStream);
                myStream.Position = 0;
                var r = mySerializer.Deserialize(myStream);
                return (Result)r;
         }

    }

    [Serializable]
    public class Result
    {
        [XmlAttribute]
        public string someString { get; set; }
        [XmlAttribute]
        public bool someBool { get; set; }
        [XmlAttribute]
        public int someInt { get; set; }
        [XmlAttribute]
        public float someFloat { get; set; }

    }

}

【问题讨论】:

    标签: c# xml-serialization


    【解决方案1】:

    您可以使用DefaultValueAttribute 为未初始化的字段提供默认值。在你的情况下,你可以写

    using System.ComponentModel;
    using System.Configuration;
    
    [XmlAttribute, DefaultValue(true)]
    public bool someBool { get; set; }
    

    编辑。请看MSND页面上的注释note on MSDN:

    DefaultValueAttribute 不会导致 自动成为成员 用属性初始化 价值。您必须设置初始值 在你的代码中。

    XML serialization and DefaultValue("") related problem in c# 中也解决了此问题。 因此,要设置默认值,您必须在代码中指定这些值。


    我希望这会有所帮助。

    【讨论】:

    • 我已经看过了。反序列化空属性似乎没有任何作用。你能告诉我我在寻找与我的例子相关的具体内容吗?谢谢
    • 这个 [XmlElementAttribute(IsNullable = false)] 在序列化为 xml 但不能反序列化时似乎可以工作。
    • 该属性在反序列化时没有影响。我也试过 [XmlAttribute, DefaultValue(null)] 也没有影响。
    • -1 问题中哪里提到了DefaultValueAttribute?
    • 如果可以,请重新编辑,因为当前的解决方案不起作用。布尔?导致序列化程序中出现反射错误,并且文档说不能序列化可空类型。
    【解决方案2】:

    ints 和 floats 不能有空值 - 它们的默认值分别是 0 和 false。

    如果应该允许它们为空,则将其更改为可空类型:

    [Serializable]
    public class Result
    {
        [XmlAttribute]
        public string someString { get; set; }
        [XmlAttribute]
        public bool? someBool { get; set; }
        [XmlAttribute]
        public int? someInt { get; set; }
        [XmlAttribute]
        public float? someFloat { get; set; }
    }
    

    请注意,使用此类型的任何内容现在都必须先使用 HasValue 检查空值,然后才能使用这些字段和/或使用 Value 属性访问值。

    【讨论】:

    • 如文档中所述,将它们设为可空类型在这里无济于事。事实上,使它们可以为空意味着它们变得不可序列化 XmlSerializer!
    【解决方案3】:

    您可以实现ISerializable接口并使用GetObjectData方法。

    请查看Custom Serialization

    【讨论】:

      【解决方案4】:

      你可以尝试使用这样的东西:

          [XmlAttribute]
          public bool someBool { get; set; }
          [XmlIgnore]
          public bool someBoolSpecified { get; set; }
          [XmlIgnore]
          public bool? SomeBool
          {
              get
              {
                  return someBoolSpecified ? someBool : default(bool?);
              }
              set
              {
                  someBoolSpecified = value != default(bool?);
                  someBool = value ?? default(bool);
              }
          }
      

      根据XmlSerializer documentation:

      另一种选择是使用特殊模式来创建 XmlSerializer 识别的布尔字段,并将 XmlIgnoreAttribute 应用于该字段。该模式以 propertyNameSpecified 的形式创建。例如,如果有一个名为“MyFirstName”的字段,您还将创建一个名为“MyFirstNameSpecified”的字段,它指示 XmlSerializer 是否生成名为“MyFirstName”的 XML 元素。这在以下示例中显示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-20
        • 2010-11-20
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多