Numbers and precision in JSON
A JSON number is written in decimal: an optional minus sign, digits, an optional fraction and an optional exponent, like -12.5e3. There is no leading +, no leading zeros (012), no hex, and no NaN or Infinity. The format itself sets no limit on how big or how precise a number can be.
Big integers lose digits
The limit comes from the program that reads the JSON. RFC 8259 points out that many programs use IEEE 754 double-precision numbers, and JavaScript's JSON.parse does. A double stores every integer exactly only up to 2^53 − 1, which is 9007199254740991 (Number.MAX_SAFE_INTEGER in JavaScript). Past that, some integers can't be stored, and the parser rounds to the nearest one it can, without any error.
{"id": 9007199254740993}JSON.parse('{"id": 9007199254740993}').id
// 9007199254740992The last digit changed. With IDs, that means a different record. This is why many APIs send large IDs as strings. The Twitter API, for example, sent each ID twice: as a number in id and as a string in id_str.
Decimals are rounded too
Most decimal fractions have no exact binary form, so a double stores the closest value it can. That's why 0.1 + 0.2 gives 0.30000000000000004 in JavaScript. For money, many APIs send whole cents (1480 for 14.80) or send the amount as a string.
Keeping every digit
j2n keeps the original text of every number, so formatting, copying and downloading keep every number exactly as written, trailing zeros and exponents included. Integers above 2^53 − 1 get a "Big number" label, so you can see which values other tools may change.
In your own JavaScript, send big IDs as strings where you can. Where you can't, recent versions of Chrome and Node.js pass the original text of each number to a JSON.parse reviver, as context.source, so you can turn it into a BigInt.