C# 将十进制数序列化为 XML

23
我有一个十进制属性,类似于: [XmlElementAttribute(DataType = "decimal")] decimal Price 问题是,我想始终强制将其序列化为精度为2,但如果价格是10.50,则将其序列化为XML如下: <Price>10.5</Price> 是否有方法可以强制执行此操作(而无需创建新属性或更改此属性的get?我正在寻找一种只发送模式到XmlSerializer(或XmlElementAttribute)或任何聪明的方法来实现这一点?
谢谢

我也遇到了同样的问题,并发现了你所提出的问题,然后找到了一个不同的答案。看看吧。 - Jim McKeeth
1
@Jim......那答案到底是什么?要不给个链接? - JK.
@JK 我认为这是下面的 - Jim McKeeth
如何在 XML 序列化中强制小数精度 - flash
3个回答

30

我遇到了相反的问题。我的小数被序列化为4位小数,尽管它们都是4个零。我发现如果我调用decimal.Round(value, 2),它就会序列化为2个小数位。似乎Decimal类型会在序列化时记住上一次舍入的结果。

我对这个建议持怀疑态度,但它确实如此简单有效。即使值不需要舍入,调用Round也会改变序列化中出现的小数位数。


不错!我所做的只是在设置数值时使用带有所需精度的 decimal.Round。这才是真正的答案! - Schultz9999
我需要输出一个硬编码值为“0.00”,在VB.NET中,这是唯一有效的方法:Decimal.Round(0.00D, 2)。 - James Hulse
1
它能够工作是因为十进制存储浮点值(即550.0000被存储为5500000 * 10^-4,如果你将其舍入到2个小数位,它将变成55000 * 10^-2),而且显然序列化器只是取出其中的内容,然后根据指数放置小数点。 - Goran Obradovic
4
如果你有一个带一位小数的十进制数,并试图将其舍入到两位小数,那么这种方法不起作用。 - DanBrum
4
我会这样做:decimal.Round(value*1.00m, 2)。 - LDW

8
您可以在实际的十进制属性上添加 XmlIgnore,并引入一个新的属性 PriceAsString,返回价格的字符串表示形式(以10.50格式)。
当然,您也可以实现 IXmlSerializable 并自己完成所有操作。
然而,这些方式都不是最好的选择,而且您已经声明了不会走这条路...

1
我有几个 int 类型的变量,我将它们赋值给需要序列化的对象的 decimal 属性。XML Serializer 应该将它们写成两位小数,但实际输出时没有小数。
假设
var myInt = 3;

没有成功:

通过序列化设置需要序列化的属性

obj.Property = decimal.Round((decimal)myInt, 2);

在序列化时,不会写入任何小数。

成功:

使用

obj.Property = decimal.Parse(d.ToString("n2", CultureInfo.InvariantCulture), NumberStyles.Any, CultureInfo.InvariantCulture);

我得到了两个小数。

现在我知道如何在设置属性时使用这些扩展方法:

/// <summary>
/// For XML serialization.
/// </summary>
public static class DecimalSerializationHelper
{
    public static decimal WithTwoDecimals(this decimal d)
        => decimal.Parse(d.ToString("n2", CultureInfo.InvariantCulture), NumberStyles.Any, CultureInfo.InvariantCulture);

    public static decimal WithTwoDecimals(this int x) => ((decimal)x).WithTwoDecimals();
}

以便使其读起来像

obj.Property = myInt.WithTwoDecimals();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接