JamesNK / Newtonsoft.Json

Json.NET is a popular high-performance JSON framework for .NET
https://www.newtonsoft.com/json
MIT License
10.73k stars 3.25k forks source link

Different deserialization behavior when using converter attribure with decimals #2839

Open feeleen opened 1 year ago

feeleen commented 1 year ago

// dummy converter
public class DecimalJsonConverter : JsonConverter
    {
        public override bool CanRead { get { return false; } }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override bool CanConvert(Type objectType)
        {
            throw new NotImplementedException();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }

    class DecimalObject
    {
        [JsonConverter(typeof(DecimalJsonConverter))]
        public decimal Bad { get; set; }

    public decimal Good { get; set; }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            string val = "{ \"Bad\":99999999.99999999, \"Good\":99999999.99999999 }";
            var res = JsonConvert.DeserializeObject<DecimalObject>(val);
            Console.WriteLine("Bad: " + res.Bad + ", Good: " + res.Good);
        }
    }

https://dotnetfiddle.net/tnL06K

Result is: Bad: 100000000, Good: 99999999.99999999

Bad is rounded, but Good is not. only difference is that Bad has converter attribute, which doesnt do any work here maybe there is some unnecessary conversion to double when using attribute?

is this a bug? is there any workaround?

elgonzo commented 1 year ago

Nice catch.

It's definitely not desired nor sensible behavior. If the json converter does not apply, then the value should be processed as if the json converter simply isn't there...

maybe there is some unnecessary conversion to double when using attribute?

It very much seems so, because you can influence the behavior by setting the FloatParseHandling setting to FloatParseHandling.Decimal (https://dotnetfiddle.net/beqQAh). This could count as a workaround, but in my subjective opinion it should not be an expected nor required usage pattern to do such seemingly arbitrary adjustments to the serialization settings in an attempt to achieve consistency in deserialization behavior.