使用XmlSerializer反序列化XML后字段全为Null的问题求助
反序列化XML时对象字段全为Null的问题解决
我一眼就看出问题出在哪了——你用错了序列化器,而且类的序列化属性和XML结构不匹配,导致XmlSerializer根本没法正确解析你的数据。
先给你拆解下核心问题:
- 你自动生成的类用的是WCF的
[DataContract]和[CollectionDataContract]属性,这些是给DataContractSerializer用的,而你代码里用的是XmlSerializer,这俩完全不兼容!XmlSerializer只认传统的[XmlRoot]、[XmlElement]这类XML序列化属性,对DataContract系列的属性视而不见,自然解析不出任何字段值,全是null。 - 另外还有两个小坑:
- 你的类定义里指定了命名空间
http://tempuri.org/,但XML里根本没加这个命名空间,就算用对了序列化器也会匹配失败。 - 集合类
ArrayOfServiceQualificationResponse的CollectionDataContract里指定了ItemName="ResponseItem",但XML里的子元素是<ServiceQualificationResponse>,名称完全不对应,也会导致解析不到子对象。
- 你的类定义里指定了命名空间
接下来给你两种可行的解决方案,选哪种看你的需求:
方案一:改用DataContractSerializer(推荐,因为类是用DataContract生成的)
把代码里的XmlSerializer换成DataContractSerializer,同时调整类的属性或者XML来匹配命名空间和元素名称:
步骤1:修正类的属性(如果不想改XML的话)
调整集合类和数据类的命名空间为空白,并且把集合项名称改成XML里的实际元素名:
[System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] [System.Runtime.Serialization.CollectionDataContractAttribute( Name="ArrayOfServiceQualificationResponse", Namespace= "", // 改成和XML一致的空命名空间 ItemName="ServiceQualificationResponse")] // 改成XML里的子元素名 [System.SerializableAttribute()] public class ArrayOfServiceQualificationResponse : System.Collections.Generic.List<Primus.Opticomm.Gateway.ExternalProxy.OpticommB2BService.ServiceQualificationResponse> { } [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")] [System.Runtime.Serialization.DataContractAttribute( Name="ServiceQualificationResponse", Namespace= "")] // 同样改成空命名空间 [System.SerializableAttribute()] public partial class ServiceQualificationResponse : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged { // 确保每个字段都有[DataMember(Name="字段名")]属性,比如: [System.Runtime.Serialization.DataMember(Name="status_code")] public string status_code { get; set; } // 其他字段同理... }
步骤2:替换序列化器代码
把原来的XmlSerializer代码换成DataContractSerializer:
var serializer = new DataContractSerializer(typeof(ArrayOfServiceQualificationResponse)); using (var xmlReader = XmlReader.Create(stringReader)) { ArrayOfServiceQualificationResponse obj = (ArrayOfServiceQualificationResponse)serializer.ReadObject(xmlReader); return obj; }
这样就能正确解析出所有字段值了。
方案二:修改类以兼容XmlSerializer
如果你一定要用XmlSerializer,那需要把类的DataContract属性换成XML序列化相关的属性:
[XmlRoot("ArrayOfServiceQualificationResponse")] public class ArrayOfServiceQualificationResponse : List<ServiceQualificationResponse> { [XmlElement("ServiceQualificationResponse")] public new List<ServiceQualificationResponse> Items { get { return base.ToList(); } set { base.Clear(); base.AddRange(value); } } } [XmlRoot("ServiceQualificationResponse")] public partial class ServiceQualificationResponse : INotifyPropertyChanged { [XmlElement("status_code")] public string status_code { get; set; } [XmlElement("property_id")] public string property_id { get; set; } // 其他字段都加上对应的XmlElement属性... }
然后继续用你原来的XmlSerializer代码就能正常解析了。
最后提醒下:不管用哪种方案,都要确保类里的字段名称和XML里的元素名完全一致(包括大小写和下划线),序列化器对名称匹配是严格区分的。
内容的提问来源于stack exchange,提问作者user2260040
相关产品推荐
相关产品推荐

