Text and data

Why large JSON numbers change in JavaScript

A JSON number can be valid syntax and still change when JavaScript parses it. Integers above Number.MAX_SAFE_INTEGER may lose precision. If you need an exact identifier, transmit it as a string. JSON Formatter uses JavaScript parsing and has the same limitation.

JSON parsing produces formatted values, while errors indicate invalid syntax.
Syntactic validity and exact numeric preservation are different properties.

Compare the original digits with the parsed result

Run this synthetic example in a JavaScript console. The original JSON text contains 9007199254740993, but the parsed Number rounds to 9007199254740992. Stringifying later cannot recover the lost digit.

Number.MAX_SAFE_INTEGER is 9007199254740991. Some larger integers happen to be representable, but adjacent integers are no longer all distinguishable. Do not use a successful test with one large value as proof that an identifier range is safe.

const raw = '{"id":9007199254740993}';
const value = JSON.parse(raw);
console.log(value.id);              // 9007199254740992
console.log(JSON.stringify(value)); // {"id":9007199254740992}
console.log(Number.isSafeInteger(value.id)); // false

Preserve identifiers before parsing

If an order number, database key or account identifier is not used for arithmetic, agree on a string representation in the API contract. This also preserves leading zeroes. Fix the producing system rather than guessing the original digits after rounding.

BigInt can represent large integers in JavaScript, but JSON does not have a BigInt literal. JSON.stringify on a plain BigInt throws unless you provide a serialization policy. A schema and producer/consumer agreement are still needed.

For payloads you cannot change, use a parser designed to preserve numeric tokens or a supported source-aware parsing technique. An ordinary reviver receiving an already rounded Number cannot restore the original value merely by calling BigInt(value).

const raw = '{"id":"9007199254740993","count":3}';
const value = JSON.parse(raw);
console.log(value.id); // exact string
const exact = BigInt(value.id);
console.log(exact + 1n); // 9007199254740994n

Check a formatting workflow without corrupting evidence

Keep an untouched copy of the source file. Use Text Diff to compare the source with formatted output if necessary, but remember that whitespace changes can make a raw diff noisy. Inspect the numeric fields explicitly.

Do not submit signed or precision-sensitive data to a parse-and-reserialize workflow unless its contract permits changes. Formatting also does not check schema constraints or prove that the content is trustworthy.

For a regression check, test the maximum expected identifier, adjacent values, a leading-zero string and a round trip through every service that handles the payload. Perform arithmetic assertions only after choosing a numeric type with the required range and precision.

References

Use the linked specifications and product documentation to check behavior in your own environment.

Continue troubleshooting

Related tools

Frequently asked questions

Is this invalid JSON syntax?

No. The precision limitation belongs to the consumer’s number representation.

Does pretty-printing preserve every large integer?

No. A formatter that parses JavaScript Numbers can round values before displaying them.

Can converting a rounded Number to BigInt fix it?

No. The conversion preserves the rounded value, not the original JSON digits.

Need help with a tool or found a bug?

Report an issue directly to engineering. No accounts required — all client data remains private on your device.

Report an Issue →