aspnetcore
aspnetcore copied to clipboard
[System.Text.Json] Serializer loses precision on ulong
Description
Serializing an ulong to JSON within asp.net core loses precision. Stumbled over this while upgrading an older project from traditional ASPnet to .net core 8.
Reproduction Steps
Using .net 8 and System.Text.Json 8.0.0.
public class Test
{
public ulong Key { get; set; }
}
Exposing data via minimal API
app.MapGet("/api/test", async (HttpContext context) =>
{
return new Test() { Key = 2121241830635120343 };
});
The result in the browser is the following:
{
"Key": 2121241830635120400
}
Expected behavior
{
"Key": 2121241830635120343
}
Actual behavior
{
"Key": 2121241830635120400
}
Regression?
No response
Known Workarounds
For the moment I have written a custom JsonConverter which calls ToString for the ulong myself.
Configuration
.net 8, running x64 (emulated on win dev kit arm64) on Windows 11.
System.Text.Json 8.0.0
Other information
No response
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.
Issue Details
Description
Serializing an ulong to JSON within asp.net core loses precision. Stumbled over this while upgrading an older project from traditional ASPnet to .net core 8.
Reproduction Steps
Using .net 8 and System.Text.Json 8.0.0.
public class Test
{
public ulong Key { get; set; }
}
Exposing data via minimal API
app.MapGet("/api/test", async (HttpContext context) =>
{
return new Test() { Key = 2121241830635120343 };
});
The result in the browser is the following:
{
"Key": 2121241830635120400
}
Expected behavior
{
"Key": 2121241830635120343
}
Actual behavior
{
"Key": 2121241830635120400
}
Regression?
No response
Known Workarounds
For the moment I have written a custom JsonConverter which calls ToString for the ulong myself.
Configuration
.net 8, running x64 (emulated on win dev kit arm64) on Windows 11.
System.Text.Json 8.0.0
Other information
No response
Author: | queequac |
---|---|
Assignees: | - |
Labels: |
|
Milestone: | - |
Javascript number is defined as double. See https://github.com/dotnet/runtime/issues/60780#issuecomment-949911839 and related discussions.
@huoyaoyuan JavaScript numbers, sure, but this is JSON, in which numbers are arbitrary-precision.
I would expect the full value (in the big-int case as well).
EDIT: As it turned out (see below), the issue is not so much with ASP.NET but rather with imprecise json number presentation in the MS Edge browser. Uff...
It appears to be ASP.NET Core's doing, employing a custom/specific STJ configuration serialization. STJ itself has no problem serializing ulong's correctly (https://dotnetfiddle.net/l248U1). I therefore would not see it as a problem of STJ, but an issue related to ASP.NET Core's serialization configuration.
It seems to be aspnetcore specific, I'm not sure why though. Transferring to the relevant repo for triage.
Thanks for reporting this issue, @queequac. I appreciate your patience as I work through the backlog of bug reports here.
I, unfortunately, wasn't able to repro this locally with the following sample using either both RDG (dynamic code-gen) or RDF (static code-gen).
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
ulong number = 2121241830635120343;
app.MapGet("/primitive", () => number);
app.MapGet("/complex", () => new Test { Key = number });
app.Run();
class Test
{
public ulong Key { get; set; }
}
You mentioned that you discovered this problem while migrating a previous codebase. Is the repro missing a detail that only shows up in the code you are migrating?
I wonder if this is the same issue as #55571?
Hi @captainsafia ,
thanks for reaching out. Actually I can easily reproduce the issue with an empty net8.0 web api project from scratch:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGet("/test", () =>
{
ulong x = ulong.MaxValue - 3; // 18446744073709551612
return x; // results in 18446744073709552000
});
app.Run();
Same with your sample above, it does not return 2121241830635120343 but 2121241830635120400 for /primitive (I used the project template without native-aot)
@martincostello Oh wow, thanks for the hint. @captainsafia Indeed ASP.NET is not doing anything wrong here. While I am NOT using Swagger, surprisingly Microsoft Edge is showing the resulting data with Javascript precision. The developer tools' network view shows the correct number on the wire.🤯 Google Chrome does also show the ulong in the document as-is, only Edge seems (since recently?) to ‘translate’ internally into standard-compliant JavaScript before rendering. Actually not sure if that is a good thing Edge is doing here... maybe raise an issue there, @gregsdennis , if precision in JSON is not equivalent to precision in Javascript.
maybe raise an issue there, @gregsdennis , if precision in JSON is not equivalent to precision in Javascript. - @queequac
Not sure where you're suggesting I raise an issue, or for what.
maybe raise an issue there, @gregsdennis , if precision in JSON is not equivalent to precision in Javascript. - @queequac
Not sure where you're suggesting I raise an issue, or for what.
You mentioned above
JavaScript numbers, sure, but this is JSON, in which numbers are arbitrary-precision.
In this case handling json-documents in edge's rendering should maybe also not lose precision. Anyway, personally no hard feelings about this.🙃
Okay, but JSON and JS number handling are inherently defined differently.
While JSON numbers are theoretically unlimited in scale and precision, JS does define those limitations, so if you're interpreting JSON through JS, it's totally understandable that you'll encounter those limits.
There is no issue that I can file in any repo that's going to help this.
My point in that comment was that if this were an STJ problem, then it should serialize the ulong
fully. But it turned out to not be an STJ issue.
The behavior of Asp.Net could do what it feels is right given its domain is web services.
There is no issue that I can file in any repo that's going to help this.
You have completely misunderstood me. :) It was not my intention to change JS or JSON. It was more about potentially opening an issue for Ms Edge, since it handles numbers in JSON documents like numbers in JS.
Anyway, nothing else to discuss here.