C#如何将List对象序列化为XML

17次阅读

xmlSerializer序列化List需T为public类、含无参构造函数及public读写属性;须传typeof(List),支持Xml特性定制根名与命名空间,不支持私有字段、只读属性、Dictionary等。

C#如何将List对象序列化为XML

XmlSerializer 序列化 List 是最直接的方式

只要类型 T 是公共类、有无参构造函数、所有要序列化的字段/属性是公共的,XmlSerializer 就能正常工作。它不支持私有字段、只读属性(除非有 public setter)、Dictionary 或匿名类型。

常见错误现象:InvalidOperationException 提示“无法序列化类型 System.Collections.Generic.List`1”,通常是因为没传入泛型类型的具体类型信息,或目标类里有不可序列化的成员。

  • 必须显式传入 typeof(List) 构造 XmlSerializer,不能只传 typeof(T)
  • 如果 T 有自定义属性(如 [XmlIgnore][XmlElement("Name")]),它们会生效
  • 序列化结果中默认根元素名是 ArrayOfType,可通过包装类或 XmlRoot 特性控制
var list = new List {     new Person { Name = "Alice", Age = 30 },     new Person { Name = "Bob", Age = 25 } };  var serializer = new XmlSerializer(typeof(List)); using (var writer = new StringWriter()) {     serializer.Serialize(writer, list);     Console.WriteLine(writer.ToString()); }

Person 类必须满足基本可序列化要求

XmlSerializer 不会报错但静默跳过不可序列化成员,比如没有 getter/setter 的属性、internalprivate 字段、Static 成员。务必检查生成的 XML 是否包含预期字段。

容易踩的坑:忘记加无参构造函数,或把属性写成 public string Name { get; }(只读)——这会导致该字段不出现在 XML 中。

  • 类必须是 public
  • 每个要序列化的属性必须有 public getter 和 setter
  • 必须有 public 无参构造函数(编译器自动生成的也行)
  • 避免在属性 getter 中抛异常或访问外部资源
public class Person {     public Person() { } // 必须存在      public string Name { get; set; } // ✅ 可序列化     public int Age { get; set; }     // ✅ 可序列化     public string InternalId { get; private set; } // ❌ 不会出现在 XML 中 }

想自定义根节点名或去掉默认命名空间?用 XmlRootXmlSerializerNamespaces

默认输出带 xmlns:xsixmlns:xsd,多数场景不需要。根元素叫 ArrayOfPerson 也不够直观。这两个问题可以一起解决。

注意:XmlRoot 特性只能加在类上,对 List 本身无效;所以更稳妥的做法是封装一层容器类,或者用 XmlSerializer 构造时传入 XmlRootAttribute 实例。

  • 传入 new XmlRootAttribute("People") 可改根名
  • XmlSerializerNamespaces 添加空前缀可移除默认命名空间
  • 若用容器类(如 PeopleCollection),直接在类上加 [XmlRoot("People")] 更清晰
var serializer = new XmlSerializer(     typeof(List),     new XmlRootAttribute("People"));  var ns = new XmlSerializerNamespaces(); ns.Add("", ""); // 移除默认命名空间  using (var writer = new StringWriter()) {     serializer.Serialize(writer, list, ns);     Console.WriteLine(writer.ToString()); }

别用 DataContractSerializer 替代,除非你已绑定 WCF 场景

DataContractSerializer 默认不支持 List 直接序列化,且需要显式标记 [DataContract][DataMember],XML 格式也不同(带 xmlns:i 等)。它更适合服务间契约明确的场景,不是通用 XML 生成方案。

如果你只是导出配置、日志或简单数据交换,坚持用 XmlSerializer。混用两种序列化器容易导致反序列化失败或字段丢失。

  • XmlSerializer 基于公有成员,约定优先,适合人读 XML
  • DataContractSerializer 基于显式契约,适合跨平台服务通信
  • 二者生成的 XML 结构、命名空间、空值处理逻辑都不同,不能互换

真正麻烦的点在于:一旦 T 类型嵌套了其他泛型集合、接口类型或含循环引用,XmlSerializer 会直接失败,而且错误信息非常模糊。这种时候要么重构模型,要么换 jsON。

text=ZqhQzanResources