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!