求助:XmlSerializer序列化时输出默认属性值,自定义XmlTextWriter无效
解决XmlSerializer不输出默认值属性的问题
你遇到的核心问题其实不是XmlTextWriter的问题——XmlSerializer在序列化时,如果属性值等于DefaultValueAttribute指定的默认值,它会直接跳过生成这个属性节点,所以你的DefaultValueXmlTextWriter根本没机会处理这个属性,自然不管怎么改WriteAttributes的参数都没用。
下面给你两种可行的解决方案:
方案一:使用XmlAttributeOverrides强制输出属性
你可以通过XmlAttributeOverrides来覆盖原类的序列化设置,移除默认值的判断逻辑,让XmlSerializer始终输出该属性:
// 创建覆盖规则,移除isActive的DefaultValue设置 XmlAttributeOverrides overrides = new XmlAttributeOverrides(); XmlAttributes attrs = new XmlAttributes(); // 关键:不保留原DefaultValueAttribute,让XmlSerializer跳过默认值判断 attrs.XmlAttribute = new XmlAttributeAttribute(); overrides.Add(typeof(Foo), "isActive", attrs); // 使用覆盖后的设置创建XmlSerializer XmlSerializer serializer = new XmlSerializer(typeof(Foo), overrides); // 后续序列化代码不变 XmlSerializerNamespaces ns = new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName("", "") }); Foo f = new Foo(); f.content = "hello"; f.isActive = false; string fStr; using (MemoryStream ms = new MemoryStream()) using (XmlWriter wr = new XmlTextWriter(ms, new UTF8Encoding(false))) { serializer.Serialize(wr, f, ns); ms.Position = 0; using (StreamReader sr = new StreamReader(ms)) { fStr = sr.ReadToEnd(); } }
这样不管isActive的值是true还是false,都会被输出为属性。如果你的需求是仅当值等于默认值时才输出,可以在序列化前判断属性值,动态调整覆盖规则。
方案二:实现IXmlSerializable接口自定义序列化
如果需要更精细的控制(比如只输出默认值属性、完全自定义Xml结构),可以让Foo类实现IXmlSerializable接口:
[Serializable] [XmlType(AnonymousType = true)] [XmlRoot(Namespace = "", IsNullable = false)] public class Foo : IXmlSerializable { public string content { get; set; } [DefaultValue(true)] public bool isActive { get; set; } public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { // 实现反序列化逻辑 reader.ReadStartElement(); content = reader.ReadElementContentAsString("content", ""); if (reader.MoveToAttribute("isActive")) { isActive = bool.Parse(reader.Value); reader.MoveToElement(); } else { // 无属性时使用默认值 isActive = true; } reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { // 自定义序列化:先写content元素 writer.WriteElementString("content", content); // 按照你的需求:始终写出isActive属性(也可改成仅默认值时输出) writer.WriteAttributeString("isActive", isActive.ToString().ToLower()); } }
这种方式完全由你控制Xml的生成,灵活性最高,想输出什么结构就输出什么结构。
补充:为什么你的XmlTextWriter子类没用?
再解释下本质原因:XmlSerializer在序列化前会先检查属性的DefaultValueAttribute,如果当前值等于默认值,它会直接跳过调用XmlWriter的WriteAttribute方法——也就是说,XmlWriter连这个属性的存在都不知道,自然无法输出它,你的子类重写也就起不到作用了。
内容的提问来源于stack exchange,提问作者Kjara
相关产品推荐
相关产品推荐

