Serializing a decimal to JSON, how to round off?

Halvard picture Halvard · Sep 5, 2012 · Viewed 33.4k times · Source

I have a class

public class Money
{
    public string Currency { get; set; }
    public decimal Amount { get; set; }
}

and would like to serialize it to JSON. If I use the JavaScriptSerializer I get

{"Currency":"USD","Amount":100.31000}

Because of the API I have to conform to needs JSON amounts with maximum two decimal places, I feel it should be possible to somehow alter the way the JavaScriptSerializer serializes a decimal field, but I can't find out how. There is the SimpleTypeResolver you can pass in the constructor, but it only work on types as far as I can understand. The JavaScriptConverter, which you can add through RegisterConverters(...) seems to be made for Dictionary.

I would like to get

{"Currency":"USD","Amount":100.31}

after I serialize. Also, changing to double is out of the question. And I probably need to do some rounding (100.311 should become 100.31).

Does anyone know how to do this? Is there perhaps an alternative to the JavaScriptSerializer that lets you control the serializing in more detail?

Answer

BrandonLWhite picture BrandonLWhite · Sep 23, 2014

I wasn't completely satisfied with all of the techniques thus far to achieve this. JsonConverterAttribute seemed the most promising, but I couldn't live with hard-coded parameters and proliferation of converter classes for every combination of options.

So, I submitted a PR that adds the ability to pass various arguments to JsonConverter and JsonProperty. It's been accepted upstream and I expect will be in the next release (whatever's next after 6.0.5)

You can then do it like this:

public class Measurements
{
    [JsonProperty(ItemConverterType = typeof(RoundingJsonConverter))]
    public List<double> Positions { get; set; }

    [JsonProperty(ItemConverterType = typeof(RoundingJsonConverter), ItemConverterParameters = new object[] { 0, MidpointRounding.ToEven })]
    public List<double> Loads { get; set; }

    [JsonConverter(typeof(RoundingJsonConverter), 4)]
    public double Gain { get; set; }
}

Refer to the CustomDoubleRounding() test for an example.