JSON can spell an integer with many digits, but the receiving runtime decides how that value is represented. JavaScript normally parses JSON numbers into IEEE 754 double-precision Number values. Integers beyond the safe range can be rounded before application code sees them.

The safe integer boundary

JavaScript can represent integers exactly from -(2^53 - 1) through 2^53 - 1. Number.MAX_SAFE_INTEGER is 9,007,199,254,740,991. Beyond that boundary, adjacent mathematical integers may map to the same Number value.

This matters for database identifiers, ledger units, timestamps with excessive precision and counters produced by languages with 64-bit integer types. The payload can be valid JSON while the parsed value is no longer identical to the source digits.

JSON.parse('{"id":9007199254740993}').id
// 9007199254740992

A reviver may be too late

JSON.parse supports a reviver callback, but the normal numeric conversion has already happened before the callback receives a value. Converting the rounded Number to BigInt cannot recover digits that were lost during parsing.

Some modern parsers expose source text to the reviver or provide lossless-number modes. Check the exact runtime and browser support before relying on those features. Cross-platform systems should not assume they are universally available.

Encode identifiers as strings

The most interoperable solution is to encode large integer identifiers as JSON strings. Consumers can preserve the exact digits and convert them to BigInt, decimal or a database-native integer when needed. A schema can document the string format with a digit pattern.

Avoid arithmetic on identifier strings: IDs are labels, not quantities. For monetary or measured quantities, define units and precision explicitly. Many systems send minor currency units as integer strings or use a decimal string with a documented scale.

Test the entire path

Precision can be lost in a browser, proxy, server, queue consumer, analytics pipeline or spreadsheet export. A unit test around only the first parser does not prove end-to-end safety.

Create a fixture containing the boundary values, one value above the boundary and the largest values your producer emits. Compare exact source digits at every serialization boundary. This turns a subtle production risk into a repeatable compatibility test.

Practical takeaways

  • Number.MAX_SAFE_INTEGER is the practical JavaScript boundary.
  • Valid JSON does not guarantee lossless numeric parsing.
  • Use strings for large IDs and precisely documented decimal values.
  • Test precision through every system boundary.

How this guide was prepared

JSON Anvil guides are written for working developers, checked against reproducible examples, and reviewed for technical clarity. Tool output is tested locally; readers should still validate behavior in the exact runtime used by their application.