JamesNK / Newtonsoft.Json

Json.NET is a popular high-performance JSON framework for .NET

Home Page:https://www.newtonsoft.com/json

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't de-serialise decimals having no leading zero (regression between NewtonSoft.Json 9.0.1 and 10.0.1)

sylvainrodrigue opened this issue · comments

Source/destination types

    public class TestClass
    {
        public decimal Amount { get; set; }
    }

Source/destination JSON

 "{ \"Amount\": .00}"

"{ \"Amount\": -.23}"

Expected behavior

  • "{ "Amount": .00}" --> Should return a decimal containing 0.0
  • "{ "Amount": -.23}" --> Should return a decimal containing -0.23

Actual behavior

Both examples throw an exception with NewtonSoft 10.0.1 or higher.
Both works with 9.0.1 or lower.

Exception thrown:

Newtonsoft.Json.JsonReaderException
HResult=0x80131500
Message=Input string '.00' is not a valid decimal. Path 'Amount', line 1, position 15.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.JsonTextReader.ParseReadNumber(ReadType readType, Char firstChar, Int32 initialPosition)
at Newtonsoft.Json.JsonTextReader.ParseNumber(ReadType readType)
at Newtonsoft.Json.JsonTextReader.ReadNumberValue(ReadType readType)
at Newtonsoft.Json.JsonTextReader.ReadAsDecimal()
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
at NewtonSoft_Test2.Program.Main(String[] args) in C:\Repos_Test\NewtonSoft_Test2\NewtonSoft_Test2\Program.cs:line 17

Steps to reproduce

using Newtonsoft.Json;

namespace NewtonSoft_Test2
{
    internal class Program
    {
        static void Main(string[] args)
        {
           // This works fine with versions 9.0.1 and lower. Doesn't work with 10.0.1 and higher
            var jsonString = "{ \"Amount\": .00}";
            var obj = JsonConvert.DeserializeObject<TestClass>(jsonString);
            Console.WriteLine(obj.Amount);

           // This works fine with versions 9.0.1 and lower. Doesn't work with 10.0.1 and higher
            jsonString = "{ \"Amount\": -.23}";
            obj = JsonConvert.DeserializeObject<TestClass>(jsonString);
            Console.WriteLine(obj.Amount);

            Console.ReadLine();
        }
    }

    public class TestClass
    {
        public decimal Amount { get; set; }
    }
}

I am not commenting on whether this is an accidental regression or an intenional fix/change in the behavior of the serializer, but take note that your examples are not valid json. The json format does not allow numbers featuring a decimal dot without a preceding numerical digit. As such, expect that your kind-of-but-not-really json will cause further problems if you ever decide to use something else than Newtonsoft.Json...

You're right: this is not supported by JSON. So this is a fix, not a regression.
The problem is our side. Thank you for your quick reply, much appreciated!