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

JsonConvert.DeserializeObject throwing exception when number decimal separator is comma (,). #2825

Open neha993185 opened 1 year ago

neha993185 commented 1 year ago

JsonConvert.DeserializeObject is working fine for all the culture whose decimal separator is (.) but giving exception when number decimal separator is comma (,).

UsingNewtonsoft.Json" Version="10.0.3"

//Input Json String {"max":500,"min":0,5} : Exception {"max":500,"min":0.5} : Working fine

Expected behavior

JsonConvert.DeserializeObject should not give exception when number decimal separator is comma (,).

Actual behavior

Invalid JavaScript property identifier character: }. Path 'min', line 1, position 20.

Stacktrace  at Newtonsoft.Json.JsonTextReader.ReadUnquotedPropertyReportIfDone (System.Char currentChar, System.Int32 initialPosition) [0x0005d] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonTextReader.ParseUnquotedProperty () [0x00056] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonTextReader.ParseProperty () [0x00048] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonTextReader.ParseObject () [0x000d8] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonTextReader.Read () [0x00053] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.String id) [0x002b1] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00161] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0006d] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x000db] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00054] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <7ca8898b690a4181a32a9cf767cedb1e>:0   at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in <7ca8898b690a4181a32a9cf767cedb1e>:0

Steps to reproduce

var jsonString ="{"max":500,"min":0,5}"; var deserializedObject = JsonConvert.DeserializeObject(jsonString);

elgonzo commented 1 year ago

Note that floating point numbers in json must use the decimal dot. Decimal commas are not allowed by the json standard (https://www.json.org/json-en.html; as this would conflict with the comma separator token used by the json format). Your example {"max":500,"min":0,5} is not proper json, violating the json format.

Btw, if you got json strings that should be parsed as a floating point numbers in a culture-specific way, check the documentation for JsonSerializerSettings (https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonSerializerSettings.htm). It allows you to specify a culture used by the (de)serializer.

jflaga commented 1 year ago

In ASP.NET, using Newtonsoft.Json Version="13.0.0.0", if the request headers contain Accept-Language: fr , JsonConvert.SerializeObject() uses comma as decimal delimiter even when I use "en-US" for JsonSerializerSettings

<object> = { Num = 35.00m };

var jsonSerializerSettings = new JsonSerializerSettings()
{
    Culture = System.Globalization.CultureInfo.GetCultureInfo("en-US")
};
string json= JsonConvert.SerializeObject(<object>, jsonSerializerSettings);

The variable json has "{ num: 35,00 }" as value instead of "{ num: 35.00 }"

elgonzo commented 1 year ago

@jflaga

that's a different issue from the original issue report you posted under. According to their report, the OP seems to want decimal comma in json, which is not really a good idea to begin with. You, on the other hand, seem to suffer from decimal comma, not wanting it, which is quite the opposite to the OP as i read it.

Anyways, even in the context of ASP.NET, Json.NET does not deal with HTTP headers and such stuff. So, Json.NET itself cannot and is not being affected by an HTTP header like Accept-Language: fr as it simply doesn't care nor know about HTTP headers. It is also not affected by the culture of the thread. Not evenwhen deliberately trying to sabotage the serialization by setting JsonSerializerSettings.Culture to a culture with decimal comma.

Proof: https://dotnetfiddle.net/YAzXnQ; Note how it sets the thread's culture to fr-FR, leading the Console.WriteLine to use a decimal comma. It then once serializes with fr-FR culture and once with en-US culture, yet both results use the decimal dot/period as is correct for the json format.

Given this dotnetfiddle demo, it seems to me the issue you suffer from is likely one of those: either you are using an ancient and outdated Json.NET version that might have been possibly affected by such an issue (fyi: the dotnetfiddle i linked uses Json.NET 12.0.3, which is also not the most current one anymore, the current Json.NET version at time of writing my post is 13.0.3) or your actual project is using some custom json converter - i.e., any json converter not being part of the Json.NET package itself - that is building the json structure "manually" and doing something like a naive Num.ToString() to write the numeric value(s). If that's the case, nothing the Json.NET library itself can do about it, as it can't magically fix broken/bugged 3rd-party json converters.

If you still are convinced the issue is with the Json.NET library itself despite the dotnetfiddel demo i linked to, you'll need to substantiate your claim and provide a self-contained code example (preferably also runnable on dotnetfiddle) that actually demonstrates the issue so others (including the author of the library) have a chance to reproduce it.

jflaga commented 1 year ago

Hi @elgonzo, thank you for your explanation and proof. Sorry I don't have time to replicate the issue I encountered for now. We were able to solve our problem with a solution which does not involve JsonSerializerSettings.

I will just revisit this page when I encounter again that issue I reported.