Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialize decimal same code results not match #2928

Open
HarveyJiang opened this issue Jan 11, 2024 · 3 comments
Open

Deserialize decimal same code results not match #2928

HarveyJiang opened this issue Jan 11, 2024 · 3 comments

Comments

@HarveyJiang
Copy link

Source/destination types

var str = JsonConvert.SerializeObject(new { Data = 422.3262M });

Source/destination JSON

{"message":"Place your serialized or deserialized JSON here"}

Expected behavior

output: {"Data":422.3262}

Actual behavior

output: {"Data":422.3219999999997}

Steps to reproduce

Newtonsoft.Json:13.0.2
NF4.8

Same code,
var str = JsonConvert.SerializeObject(new { Data = 422.3262M });
var obj = JsonConvert.DeserializeObject(str);

Web application obj output: 422.3219999999997
wpf or console obj output:422.3262

but web application set FloatParseHandling =FloatParseHandling.Decimal,output :422.3262,

Why do the same code results not match?

var str = JsonConvert.SerializeObject(new { Data = 422.3262M });
JsonSerializerSettings setting = new JsonSerializerSettings();
setting.FloatParseHandling = FloatParseHandling.Decimal;
var obj = JsonConvert.DeserializeObject<object>(str, setting);

web app output error:
web_error
wfp output:
wpf_ok

web application ok:
web_ok

@elgonzo
Copy link

elgonzo commented Jan 11, 2024

There is no error in the output of the web application.

Rather, the Intellisense output of the WPF app does not align with Newtonsoft.Json's default deserialization settings.

By default (unless configured otherwise), Newtonsoft.Json uses the FloatParseHandling.Double setting, which parses/deserializes floating point numbers as double values. But the value 422.3262 cannot be accurately represented by floating point types such as float or double. The value closest to 422.3262 that can be represented by a double value is 422.3219999999997.

This however poses the question of why you did not see 422.3219999999997 in the Intellisense inspector for your WPF app. I can only speculate here:

  • In your WPF app, you applied a global Newtonsoft.Json configuration with FloatParseHandling.Decimal through the JsonConvert.DefaultSettings somewhere in the app prior to OnStartup being invoked.
  • Or, the Intellisense inspector for the WPF app works slightly differently from the one used in the web app project, showing floating point numbers as rounded values, thus effectively not showing the real (System.Double) value.

I suggest you do a more fine-grained inspection of what Newtonsoft.Json did actually deserialize in your WPF app (and that bypasses possible Intellisense inspector presentation issues like the one i speculated about):

var jvalue = (JValue)((JObject)obj)["Data"];

var tokenType = jvalue.Type;
var valueType = jvalue.Value.GetType().FullName;
var fullPrecisionValue = $"{jvalue.Value:G17}";

If the Newtonsoft.Json default settings are used (i.e. no custom JsonSerializerSettings), the variables should contain the following:

tokenType: JTokenType.Float
valueType: "System.Double"
fullPrecisionValue: "422.32619999999997"

If the token type or the value type indicate a System.Decimal value being deserialized instead of a System.Double, then this is indicative of your WPF app having set up custom JsonSerializerSettings through JsonConvert.DefaultSettings prior to invoking OnStartup.

@HarveyJiang
Copy link
Author

HarveyJiang commented Jan 12, 2024

@elgonzo , Thank you for your reply。
(WPF、Console)、Web application global not set anything.

Currently, the issue is being fixed on the web by setting FloatParseHandling=FloatParseHandling.Decimal;
Based on what considerations, double is used by default。

Thanks.

@HarveyJiang
Copy link
Author

image

NF 4.8 , console output:422.3262, .net core 8 console output: 422.3219999999997, NF4.8 web application output: 422.3219999999997

var number = "422.3262";
double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double value);

It looks like it's due to different framework double.TryParse results are inconsistent;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants