-
Notifications
You must be signed in to change notification settings - Fork 8.1k
ConvertTo-Json: Treat large enums as numbers #20999
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
Conversation
efc7b9e to
a37f4d5
Compare
|
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
|
I guess it was a workaround exclusively for JS. I think we should preserve the workaround. |
|
I don't see why we should cater to one language when PowerShell is able to deserialize such numbers. The fact that enums already have a workaround with Plus that exact scenario in your link serializes just fine with newtonsoft and we don't even do it for non enum long types. PS /home/jborean> ConvertTo-Json @{foo = ([uint64]'2121241830635120343')}
{
"foo": 2121241830635120343
} |
Me too :-) However, a comment in the code points to an internal case. Only MSFT team can find the history and evaluate the relevance of this old workaround. |
|
Just to add more ammunition to the change;
|
|
Looks like that ASP issue is specific to ASP, serializing a UInt64 works just fine with both $sb = [System.Text.StringBuilder]::new()
[Newtonsoft.Json.JsonSerializer]::Create().Serialize([System.IO.StringWriter]::new($sb), @{foo=[uint64]'18446744073709551615'})
$sb.ToString()
# {"foo":18446744073709551615}
[System.Text.Json.JsonSerializer]::Serialize[hashtable](@{foo = [uint64]'18446744073709551615'})
# {"foo":18446744073709551615}Python is also fine import json
json.dumps({"foo": 18446744073709551615})
'{"foo": 18446744073709551615}' |
PowerShell actually as a few enums based on long (or ulong) |
|
The @PowerShell/wg-powershell-cmdlets reviewed this. We believe this is a good change for modern JSON. Although historically, javascript had limits of the precision of large integers due to storing numbers as double precision floats, it seems that NodeJS v10.4.0+ now has a BigInt type and also Jordan's validation that NewtonSoft, System.Text.Json, and Python all handle big ints just fine indicate that this legacy code is no longer valid. We still have a concern about how likely this will break users so we recommend putting this behind an experimental feature to also help advertise this change. We will also recommend adding telemetry to indicate how often users are hitting this code path to ensure we believe this can be non-experimental. This can be added after this PR is merged. |
SteveL-MSFT
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put behind an experimental feature
There are 1-3 in PowerShell itself (S.M.A/M.M.I) depending on your definitions [System.AppDomain]::CurrentDomain.GetAssemblies().GetTypes() | Where-Object {
$_.IsSubclassOf([Enum]) -and
$_.IsVisible -and
[Enum]::GetUnderlyingType($_) -in @([int64], [uint64])
} | Select-Object FullName, @{
N='Assembly'
E={$_.Assembly.GetName().Name}
}, @{
N='SubType'
E={[Enum]::GetUnderlyingType($_).Name}
}
I do personally disagree that we really do need to put it behind an experimental feature but I suppose it's a stepping stone to just having it be done by default.
Any docs on what exactly needs to be done for devs on this? |
|
@jborean93 the about_experimental_features doc shows what needs to be done to add experimental features in code - hope that helps |
a37f4d5 to
7a734c7
Compare
1addde6 to
8e9250a
Compare
Remove special handling from Windows PowerShell that treated enum values backed by Int64 and UInt64 as a string. This ensures that all enum types are serialized as a number and are only treated as a string when -EnumsAsStrings is specified.
8e9250a to
ea3164f
Compare
|
@SteveL-MSFT Can we merge? |
PR Summary
Remove special handling from Windows PowerShell that treated enum values backed by Int64 and UInt64 as a string. This ensures that all enum types are serialized as a number and are only treated as a string when -EnumsAsStrings is specified.
As requested this is controlled by the new experimental feature
PSSerializeJSONLongEnumAsNumber.PR Context
When using
ConvertTo-Jsonwith an Int64 or UInt64 enum type the value is converted to a string.enum LongEnum : long { LongValue = 1 } ConvertTo-Json @{key = [LongEnum]::LongValue}The current behaviour is:
{ "key": "LongValue" }The behaviour after this PR is:
{ "key": 1 }Instead this PR removes the extra code that does this as it seems to be from Windows PowerShell days. Even then WinPS can deserialize an Int64 or UInt64 value just fine. This is technically a breaking change but I find the current default is surprising and honestly probably very rare to happen in the real world.
If the user wants to preserve the old behaviour they can set
-EnumsAsStringsto have the enum be converted to a string like before.PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.PSSerializeJSONLongEnumAsNumber(which runs in a different PS Host).