Search code examples
c#jsonjavascriptserializer

Serializing a decimal to JSON, how to round off?


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?


Solution

  • In the first case the 000 does no harm, the value still is the same and will be deserialized to the exact same value.

    In the second case the JavascriptSerializer will not help you. The JavacriptSerializer is not supposed to change the data, since it serializes it to a well-known format it does not provide data conversion at member level (but it provides custom Object converters). What you want is a conversion + serialization, this is a two-phases task.

    Two suggestions:

    1) Use DataContractJsonSerializer: add another property that rounds the value:

    public class Money
    {
        public string Currency { get; set; }
    
        [IgnoreDataMember]
        public decimal Amount { get; set; }
    
        [DataMember(Name = "Amount")]
        public decimal RoundedAmount { get{ return Math.Round(Amount, 2); } }
    }
    

    2) Clone the object rounding the values:

    public class Money 
    {
        public string Currency { get; set; }
    
        public decimal Amount { get; set; }
    
        public Money CloneRounding() {
           var obj = (Money)this.MemberwiseClone();
           obj.Amount = Math.Round(obj.Amount, 2);
           return obj;
        }
    }
    
    var roundMoney = money.CloneRounding();
    

    I guess json.net cannot do this either, but I'm not 100% sure.