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

Recommend support for BigInt #36

Open
apprat opened this issue May 27, 2022 · 7 comments
Open

Recommend support for BigInt #36

apprat opened this issue May 27, 2022 · 7 comments
Assignees

Comments

@apprat
Copy link

apprat commented May 27, 2022

const object = {id: 123n}
stringify can be stored as
{"id": 123n}
Can be correctly converted to bigint instead of number during parse

@apprat
Copy link
Author

apprat commented May 27, 2022

In my current software, I can't convert bigint to string storage, which gives me a headache. My current solution is to convert bigint to string, and then add an "n" to represent bigint

@apprat
Copy link
Author

apprat commented May 27, 2022

Now in version 2.2.1, bigint will be removed when stringify

@jordanbtucker jordanbtucker changed the title Hope to support bigint Recommend support for BigInt May 27, 2022
@jordanbtucker jordanbtucker self-assigned this May 27, 2022
@jordanbtucker
Copy link
Member

jordanbtucker commented May 27, 2022

Thanks for the suggestion. JSON5 already intrinsically supports arbitrary-precision integers, as there is no limitation on how large a number can be in a JSON5 document. In fact, JSON5 has no notion of different data types for numbers, apart from the special IEEE 754 values Infinity and NaN. The specification only documents the ways in which numbers can be represented, and it is up to JSON5 parser implementations to decide what data types those numbers should be stored as in memory.

There is nothing stopping you from writing a JSON5 document like this:

{
  // This number is 2^55, and it
  // is too large to be represented
  // accurately by an IEEE 754 64-bit
  // floating-point value.
  "bigint": 36028797018963968,
}

It is JSON5 parsers and generators that impose restrictions on how this large number is handled. For example, the reference JavaScript implementation parses that number in the same way a JavaScript library would—it converts it to closest value that is able to be represented by an IEEE 754 64-bit floating-point value. However, that library could be updated to recognize that the value is an integer that is too large and then convert it to a BigInt, or a string if BigInt isn't supported on the current platform.

Adding a BigInt representation for numbers in JSON5 is not only incompatible with ECMAScript 5, but it would only add the feature of indicating the intended data type of a number. Although you could make the case that a JSON5 number with a decimal point or an exponent is intrinsically a floating-point value, and that a hexadecimal number and a number without a decimal point or exponent are both intrinsically integers, there is no intrinsic way to indicate the size or signedness of those data types (e.g. 32- vs 64-bit floating-point, 8- vs 16- vs 32- vs 64-bit vs arbitrary-precision integer, and signed vs unsigned). In other words, is the JSON5 value 100 a byte, 16-bit integer, 32-bit integer, 64-bit integer, or a BigInt, and is it signed or unsigned? There isn't a way to indicate that in JSON5 because it does not impose those kinds of data type restrictions. Adding a representation for BigInt when there are no representations for other integer types would be inconsistent.

@jordanbtucker
Copy link
Member

I created a replacer function and a reviver function for BigInt that both work with JavaScript implementations of JSON and JSON5. It converts BigInts to and from strings.

const value = -123n
const json5 = JSON5.stringify(value, bigIntReplacer)
// json5 == `'-123n'`
const json5 = `'-123n'`
const value = JSON5.parse(json5, bigIntReviver)
// value == -123n

@apprat
Copy link
Author

apprat commented May 28, 2022

I created a replacer function and a reviver function for BigInt that both work with JavaScript implementations of JSON and JSON5. It converts BigInts to and from strings.

Thanks, but converting to a string may lead to wrong judgments, I still hope to support this function, although it is indeed not compatible with ES5, but isn't the purpose of json5 to make up for the deficiencies of json?

@jordanbtucker
Copy link
Member

jordanbtucker commented May 29, 2022

I would not say that JSON's lack of numeric data type indicators is a deficiency. It's a feature that makes JSON platform agnostic and interoperable. As I already explained, JSON and JSON5 already support arbitrary-precision integers. If a JSON5 parser cannot handle large numbers, then it is not a deficiency of JSON5—it's a deficiency in the JSON5 parser or the platform. In other words, if a JSON5 parser encounters an integer that is too large for its platform's largest fixed-precision integer type, then it may read it as an arbitrary-precision integer (e.g. BigInt in JavaScript) instead, given the parser's platform has one.

@bogdanbiv
Copy link

bogdanbiv commented Jul 7, 2022

I would not say that JSON's lack of numeric data type indicators is a deficiency.

I would say that given in ECMA-232 BigInt is standardized as 1n, having a different behavior in JSON parser/s would be a major headache. At least it should be allowed as a hint or be ignored. It's useful for humans parsing the document too.

/my $0.02

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

No branches or pull requests

3 participants