.NET 8中XmlSerializer不序列化派生值问题排查
问题原因
XmlSerializer 默认只会序列化同时拥有公共 get 和 set 访问器的属性。你定义的 AmountAsString(表达式体属性,本质只读)和 AnotherTry(仅包含 get 方法)都是只读属性,不符合序列化要求,因此被忽略。即使去掉 ToString("c2"),只读属性的本质没变,结果依然不会被序列化。
解决方案
针对你的需求(将decimal序列化为保留两位小数的格式),提供以下几种可行方案:
方案1:给只读属性添加空setter
既然序列化器需要setter,我们可以给这两个属性添加一个空的公共setter,不需要任何逻辑:
[XmlRoot(Namespace = "urn:iso:std:iso:20022:tech:xsd:pain.008.001.08")] public class DecimalTestCase { [XmlElement("IAmDecimal")] public decimal Value { get; set; } [XmlElement("IAmString")] public string AmountAsString { get => Value.ToString("c2"); set { } } [XmlElement("IAmAlsoString")] public string AnotherTry { get => Value.ToString("c2"); set { } } }
这样序列化器就能识别并处理这两个属性了。
方案2:直接处理decimal值,序列化格式化后的结果
如果你不需要同时保留原decimal字段的序列化结果,可以直接将decimal值四舍五入到两位小数,或者格式化后序列化:
[XmlRoot(Namespace = "urn:iso:std:iso:20022:tech:xsd:pain.008.001.08")] public class DecimalTestCase { // 标记原字段不序列化 [XmlIgnore] public decimal Value { get; set; } [XmlElement("FormattedAmount")] public string FormattedValue => Math.Round(Value, 2).ToString("F2"); // 注:"F2"保留两位小数(无货币符号),"c2"会带货币符号,可按需选择 }
序列化后会得到<FormattedAmount>123.12</FormattedAmount>这样的结果。
方案3:实现IXmlSerializable自定义序列化逻辑
如果需要更灵活的控制,可以实现IXmlSerializable接口,完全自定义序列化过程:
[XmlRoot(Namespace = "urn:iso:std:iso:20022:tech:xsd:pain.008.001.08")] public class DecimalTestCase : IXmlSerializable { public decimal Value { get; set; } public XmlSchema GetSchema() => null; public void ReadXml(XmlReader reader) { // 按需实现反序列化逻辑 reader.ReadStartElement(); Value = decimal.Parse(reader.ReadElementContentAsString("IAmDecimal", "")); reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { // 自定义输出XML结构 writer.WriteElementString("IAmDecimal", Value.ToString()); writer.WriteElementString("IAmString", Value.ToString("c2")); writer.WriteElementString("IAmAlsoString", Math.Round(Value, 2).ToString("F2")); } }
这种方式完全由你控制输出的XML结构,适合复杂场景。
注意事项
- 若不需要货币符号,避免使用
"c2"格式符,改用"F2"确保输出纯数字格式。 - 建议先用
Math.Round(Value, 2)处理decimal值再格式化,避免ToString时的精度偏差问题。
内容的提问来源于stack exchange,提问作者MilConDoin
相关产品推荐
相关产品推荐

