Handling decimal values in Newtonsoft.Json

后端 未结 3 990
日久生厌
日久生厌 2020-11-28 08:04

Edit: It\'s been almost 5 years and I don\'t think this is the way to go. The client should post the data in the correct numerical format. With current fram

3条回答
  •  爱一瞬间的悲伤
    2020-11-28 08:09

    As an extension to Kwaazaar's answer, I have added the reverse way to the converter as well (In his example it throws a NotImplementedException.

    namespace Something.Converter
    {
        using System;
    
        using Newtonsoft.Json;
        using Newtonsoft.Json.Linq;
    
        /// 
        /// 
        /// Converts an object to and from JSON.
        /// 
        /// 
        public class DecimalConverter : JsonConverter
        {
            /// 
            /// Gets a new instance of the .
            /// 
            public static readonly DecimalConverter Instance = new DecimalConverter();
    
            /// 
            /// 
            /// Determines whether this instance can convert the specified object type.
            /// 
            /// Type of the object.
            /// 
            ///     true if this instance can convert the specified object type; otherwise, false.
            /// 
            /// 
            public override bool CanConvert(Type objectType)
            {
                return objectType == typeof(decimal) || objectType == typeof(decimal?);
            }
    
            /// 
            /// 
            /// Reads the JSON representation of the object.
            /// 
            /// The  to read from.
            /// Type of the object.
            /// The existing value of object being read.
            /// The calling serializer.
            /// The object value.
            /// 
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                if (!(reader.Value is string value))
                {
                    if (objectType == typeof(decimal?))
                    {
                        return null;
                    }
    
                    return default(decimal);
                }
    
                // ReSharper disable once StyleCop.SA1126
                if (decimal.TryParse(value, out var result))
                {
                    // ReSharper disable once StyleCop.SA1126
                    return result;
                }
    
                if (objectType == typeof(decimal?))
                {
                    return null;
                }
    
                return default(decimal);
            }
    
            /// 
            /// 
            /// Writes the JSON representation of the object.
            /// 
            /// The  to write to.
            /// The value.
            /// The calling serializer.
            /// 
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                var d = default(decimal?);
    
                if (value != null)
                {
                    d = value as decimal?;
                    if (d.HasValue)
                    {
                        d = new decimal(decimal.ToDouble(d.Value));
                    }
                }
    
                JToken.FromObject(d ?? 0).WriteTo(writer);
            }
        }
    }
    

    To plug this into your binder, just add an instance of the converter to the Converters list in the JsonSerializerSettings object:

    JsonSerializerSettings settings = new JsonSerializerSettings
    {
        // Some other settings.
        Converters = new List { new DecimalConverter() }
    };
    

    or

    JsonSerializerSettings settings = new JsonSerializerSettings
    {
        // Some other settings.
        Converters = new List { DecimalConverter.Instance }
    };
    

提交回复
热议问题