3 ms·
> It’s all interoperable because there is just that one syntax. And that syntax and specification leaves open the possibility of arbitrary precision integers.
by deathanatos 8y ago
> It’s all interoperable because there is just that one syntax.
And that syntax and specification leaves open the possibility of arbitrary precision integers. From the JSON RFC[1]:
> This specification allows implementations to set limits on the range and precision of numbers accepted.
Those limits vary by implementation. The subsequent paragraphs warn, of course, that not all implementations support sending or receiving numbers outside of certain ranges, and explicitly calls out the contiguous integer range of an IEEE double as a good range for good interoperability.
> “I want to transmit non-Json strings but claim they’re json “.
Those strings are already JSON.
There are serializers out there that support arbitrary precision integers. Python, for example, will happily serialize such integers:
In [6]: json.dumps(2 ** 512)
Out[6]: '13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096'
(This will parse in today's browsers, too, but you'll get an imprecise result, as JavaScript's Number cannot represent that value exactly. Larger numbers result in Infinity.)
[1]: https://tools.ietf.org/html/rfc8259#section-6 https://tools.ietf.org/html/rfc8259#section-6
- coke12 8y agoYup, this is exactly the problem. Currently JSON.parse() will silently truncate large numbers. This behavior made sense when there was only one numeric type in the language, but BigInt opens the door for arbitrary precision integers.
- olliej 8y agoBut you can't determine (without a suffix) whether a number you encounter is a BigInt or a floating point value that lost precision so doesn't have a decimal point.
- testvox 8y agoWhat is the one language? json serialized data can be consumed in many different languages which have very different numeric data types. The json spec even says > 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 and later more precisely defines a number in a way that does not restrict its maximum size. > A number is a sequence of decimal digits with no superfluous leading zero. It may have a preceding minus sign (U+002D). It may have a fractional part prefixed by a decimal point (U+002E). It may have an exponent, prefixed by e (U+0065) or E (U+0045) and optionally + (U+002B) or – (U+002D). The digits are the code points U+0030 through U+0039. http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf http://www.ecma-international.org/publications/files/ECMA-ST...
- olliej 8y agoin JS your number would drop precision, because it doesn't have the 'n' suffix. Because you can't mix and match numeric types, JSON.parse() cannot distinguish between a number, and a bigint. so take: "[{x:0,y:1},{x:2, y:3456789....}}]" What should JSON.parse() do? There's no reason for it to parse any of the values before the final extra precision value as a regular number, so if it parses the large one as a bigint, it would break. > (This will parse in today's browsers, too, but you'll get an imprecise result, as JavaScript's Number cannot represent that value exactly. Larger numbers result in Infinity.) Your example of python output is exactly the thing that would cause a problem. Your data will work in all existing browsers - it just loses precision. But in any browser that tries to parse it as a bigint it will result in failures, as now any subsequent arithmetic will fail because you can't (for good reasons) mix and match BigInt with non-BigInt values. You also can't actually make a decision about whether a value should be parsed into a BigInt, vs a Number. Basically, take something like 2^54 -- 18014398509481984 -- should this be parsed as a Number, or as a BigInt. It's exactly representable with a double, but it has the same value as 2^54+1 (which is not exactly representable). So should that be parsed as a BigInt or as a Number. Without a suffix (not compatible with existing spec) they cannot be distinguished, and so to retain backwards compatibility must be parsed as a Number.
- BillinghamJ 8y agoIndeed, so it would seem like the obvious solution is just to have an alternative parsing function, or perhaps for it to accept options. e.g. JSON.parse(str, null, { useBigint: true});