Add JsonNumericMode parameter to jsonDecode for opt-in all-double parsing#62777
Add JsonNumericMode parameter to jsonDecode for opt-in all-double parsing#62777fabricio-costa wants to merge 2 commits intodart-lang:mainfrom
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
…sing JSON (ECMA-404) does not distinguish between integer and floating-point numbers — both are simply "number". Dart's jsonDecode currently returns int for numbers without a decimal point and double otherwise, which causes TypeError when consuming APIs that may return either form for the same field. This adds an optional numericMode parameter to jsonDecode, JsonCodec.decode, and JsonDecoder that controls how numbers are parsed: - JsonNumericMode.preserveType (default): current behavior, no changes - JsonNumericMode.allDouble: all JSON numbers are parsed as double The implementation converts int to double at the listener level in each platform backend (VM, JS runtime, WASM), keeping the performance-critical parseNumber logic untouched. Closes dart-lang#62776 See also dart-lang#46883, dart-lang#55499
ac6d163 to
912d513
Compare
|
Thank you for your contribution! This project uses Gerrit for code reviews. Your pull request has automatically been converted into a code review at: https://dart-review.googlesource.com/c/sdk/+/483941 Please wait for a developer to review your code review at the above link; you can speed up the review if you sign into Gerrit and manually add a reviewer that has recently worked on the relevant code. See CONTRIBUTING.md to learn how to upload changes to Gerrit directly. Additional commits pushed to this PR will update both the PR and the corresponding Gerrit CL. After the review is complete on the CL, your reviewer will merge the CL (automatically closing this PR). |
|
Thank you for your contribution! This project uses Gerrit for code reviews. Your pull request has automatically been converted into a code review at: https://dart-review.googlesource.com/c/sdk/+/483940 Please wait for a developer to review your code review at the above link; you can speed up the review if you sign into Gerrit and manually add a reviewer that has recently worked on the relevant code. See CONTRIBUTING.md to learn how to upload changes to Gerrit directly. Additional commits pushed to this PR will update both the PR and the corresponding Gerrit CL. After the review is complete on the CL, your reviewer will merge the CL (automatically closing this PR). |
Summary
JsonNumericModeenum todart:convertwith two values:preserveType(default) andallDoublenumericModeparameter tojsonDecode(),JsonCodec.decode(), andJsonDecoderallDoubleis used, all JSON numbers are parsed asdouble, aligning with ECMA-404's single "number" typeThis is 100% backwards compatible — the default behavior is unchanged.
Motivation
jsonDecode('{"price": 5}')returnsintforprice, butjsonDecode('{"price": 5.0}')returnsdouble. Since JSON makes no distinction between the two, this causesTypeErrorin Flutter apps when a backend returns a number without a decimal point for a field expected asdouble.The current workaround (
(json['x'] as num).toDouble()) must be applied manually to every double field in every model class. This proposal provides an opt-in solution at the parser level.Related issue: #62776
See also: #46883, #42622, #55499, #56913
Implementation
The conversion happens at the listener level, not in
parseNumber:_JsonListener.handleNumberconvertsint→doublewhenallDoubleJSON.parsepost-processing with int→double synthetic reviver_JsonListener.handleIntegerNumbershort-circuits todoubleThis keeps the performance-critical parsing code untouched. Zero overhead when using the default
preserveTypemode.Usage
Files changed
sdk/lib/convert/json.dart— public API (enum + parameters)sdk/lib/_internal/vm/lib/convert_patch.dart— VM backendsdk/lib/_internal/js_runtime/lib/convert_patch.dart— JS backendsdk/lib/_internal/wasm/lib/convert_patch.dart— WASM backendtests/lib/convert/json_numeric_mode_test.dart— test coverageTest plan
tests/lib/convert/json_*tests pass (backwards compat)json_numeric_mode_test.dartcovers:preserveTypebehavior unchangedallDoubleconverts integers to double (basic, zero, negative, large)JsonCodec.decode()andJsonDecoderconstructor paths