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

Json decoding is not JSON-compliant because of int/double parsing #46883

Closed
Hixie opened this issue Aug 11, 2021 · 2 comments
Closed

Json decoding is not JSON-compliant because of int/double parsing #46883

Hixie opened this issue Aug 11, 2021 · 2 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-not-planned Closed as we don't intend to take action on the reported issue library-convert

Comments

@Hixie
Copy link
Contributor

Hixie commented Aug 11, 2021

The following three JSON files are semantically identical according to the JSON standards:

  1. { "list": [ "a", "b", "c" ], "index": 1 }
  2. { "list": [ "a", "b", "c" ], "index": 1.0 }
  3. { "list": [ "a", "b", "c" ], "index": 1e0 }

However, in the Dart VM they are treated differently. For example, consider the following code:

import 'dart:convert';

// `input` is expected to be a JSON string in the following form:
//
// ```
// {
//   'list': [ 'a', 'b', 'c' ],
//   'index': 1,
// }
// ```
//
// That is, an object with two keys, one of which, `list`, contains an array of
// values, and the other, `index`, contains a reference to one of the values by
// identifiying its index in the array. In the example above, 'b' is identified.
Object? test(String input) {
  final dynamic model = json.decode(input);
  final dynamic index = model['index'];
  return model['list'][index];
}

void main() {
  print(test('{ "list": [ "a", "b", "c" ], "index": 1 }'));
  print(test('{ "list": [ "a", "b", "c" ], "index": 1.0 }'));
  print(test('{ "list": [ "a", "b", "c" ], "index": 1e0 }'));
}

I'm not really sure what the right answer is here. It's probably "wontfix", and the documentation requested in #46682 should just say that developers should not rely on the returned values being int or double and should instead always say toInt() or toDouble() as desired. I could also see an argument that we should always use double, since that would be less bug-prone.

@vsmenon vsmenon added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-convert labels Aug 12, 2021
@lrhn
Copy link
Member

lrhn commented Aug 13, 2021

It is indeed a wontfix.

The JSON specifications do not define semantics, only syntax.
They do not say that 1 and 1.0 represents the "same number", or even which number they represent, although the ECMA standard does mention that:

Numeric values that cannot be represented as sequences of digits (such as Infinity and NaN) are not permitted.

(Pro-tip, anything above 1.7976931348623159e+308 overflows to infinity when parsed as a double, I'd probably use 1e400, it's easier to remember and recognize, and the 00 looks like ∞).

It even goes as far as stating:

JSON is agnostic about the semantics of numbers. In any programming language, there can be a variety of
number types of various capacities and complements, fixed or floating, binary or decimal. That can make
interchange between different programming languages difficult. JSON instead offers only the representation of
numbers that humans use: a sequence of digits. All programming languages know how to make sense of digit
sequences even if they disagree on internal representations. That is enough to allow interchange.

If they did say that "1" and "1.0" must represent the same number, Dart would agree, at least up to num equality, since 1 == 1.0.

The current behavior ensures that Dart num values can be roundtripped through JSON and preserve their type and value, and that all fractional doubles are represented correctly, to the limit of double's precision.

The option of parsing large integers as BigInt is one thing we're potentially missing. If I needed that, I'd use something like package:jsontool to parse the JSON, so that I have more control and can direct access to the source representation of the number.

@lrhn lrhn closed this as completed Aug 13, 2021
@lrhn lrhn added the closed-not-planned Closed as we don't intend to take action on the reported issue label Aug 13, 2021
@rameshkec85
Copy link

rameshkec85 commented Jul 25, 2023

This should support at-least double can accept int automatically while converting. Facing lot of issues when we are using retrofit conversion. From backend servers, sometimes price can be 10, sometimes 10.5.

If i define as double should support int as well. This is one we can expect work as usual.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-not-planned Closed as we don't intend to take action on the reported issue library-convert
Projects
None yet
Development

No branches or pull requests

4 participants