Rafael Mueller
Rafael Mueller

Reputation: 6093

C# serialize decimal to xml

I got a decimal property, like

[XmlElementAttribute(DataType = "decimal")] decimal Price

The problem is that I wanna force it to serialize always with precision of 2, but if the price is 10.50 it will be serialized to XML like <Price>10.5</Price>.

Theres any way to force it (without creating a new property or changing the get of this property? I'm looking for some way to do this only sending a pattern to the XmlSerializer (or the XmlElementAttribute) or any smart way to do this ?

Thanks

Upvotes: 24

Views: 15874

Answers (3)

Jim McKeeth
Jim McKeeth

Reputation: 38713

I was having the opposite problem. My decimals were serializing with 4 decimal places, even though they were all 4 zeroes. I discovered that if I call decimal.Round(value, 2) then it serializes to 2 decimal places. It would appear that the Decimal type remembers what you last rounded it too when it is serialized.

I was suspicious of the suggestion, but it worked that simply. Even though the value didn't need rounding, calling Round changed how many decimal places showed up in serialization.

Note that as per the comments below, if the number has less than two d.p., then the decimal.Round() will do likewise and return the same number of d.p. So the best bet is to multiply by 1.00m first, which ensures the decimal holds two d.p. under the covers, i.e., decimal.Round(value * 1.00m).

Upvotes: 33

SymboLinker
SymboLinker

Reputation: 1199

I had a few ints that I assigned to decimal properties (of the object-to-serialize). They needed to be written with 2 decimals by the XML Serializer, but came out without decimals.

Assuming

var myInt = 3;

No success:

Setting a property that needs serialization via

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

results in no decimals being written at serialization.

Success:

With

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

I get two decimals.

Now I now use these extension methods at setting the properties:

/// <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();
}

so that it reads like

obj.Property = myInt.WithTwoDecimals();

Upvotes: 1

mafu
mafu

Reputation: 32710

You could add XmlIgnore to the actual decimal property and introduce a new property PriceAsString which returns, eh, the price as string (in 10.50 format).

You could of course also implement IXmlSerializable and do everything yourself.

However, none of these ways really rocks, and you already stated you were not going to go down this road anyway...

Upvotes: 9

Related Questions