JSON guide · 2 min read
JSON Numbers, Precision and Big Integers
Understand why valid JSON numbers can lose precision in JavaScript and how to handle large IDs, decimals and cross-language numeric data safely.
JSON defines number syntax, not one universal machine type
JSON can contain integer-looking and decimal-looking numbers, but each programming language maps them into its own numeric types. Range and precision therefore depend on the consumer after parsing.
JavaScript Number cannot exactly represent every large integer
JavaScript Number uses IEEE-754 double precision. Integers above Number.MAX_SAFE_INTEGER can round to a nearby representable value even though the original JSON text is syntactically valid.
Risky when every digit matters:
{"id":9007199254740993}
Safer identifier representation:
{"id":"9007199254740993"}Identifiers are often better modeled as strings
Database IDs, account numbers and external references may contain only digits but are not quantities you calculate with. Strings preserve leading zeros and avoid numeric precision differences across languages.
Money requires deliberate decimal handling
Binary floating point cannot represent every decimal fraction exactly. Applications that require exact monetary arithmetic commonly use decimal types, integer minor units or specialized libraries rather than treating floating-point JSON values as exact money.
Cross-language boundaries expose numeric differences
A Go service may decode an integer into int64, a browser into Number and a Java service into BigInteger. Define ranges in the API contract and test boundary values across consumers instead of relying on one language's defaults.
Formatting cannot restore precision already lost
Once a parser has rounded a number, pretty-printing only serializes the rounded value now in memory. Preserve critical digits as text or use an arbitrary-precision parser when exact representation is required.
Round-trip boundary values in every consumer language
For cross-service APIs, test the largest expected integers and representative decimal values through parse and serialize cycles in each major consumer. A payload that survives Java or Go may still round when it reaches a JavaScript client, and a value emitted by one service can be reformatted differently by another.
These tests are cheap and make the contract explicit. If a value is an identifier rather than a quantity, representing it as a JSON string usually removes the numeric portability problem entirely.
Primary sources
References and specifications
- RFC 8259 — The JavaScript Object Notation (JSON) Data Interchange Format
The IETF specification for JSON syntax, values, interoperability and parser behavior.
- ECMA-404 — The JSON Data Interchange Syntax
The concise ECMA definition of JSON grammar.
Common questions
Frequently asked questions
Can a valid JSON number be unsafe in JavaScript?
Yes. Valid JSON syntax does not guarantee exact representation as JavaScript Number, especially beyond the safe-integer range.
Should numeric IDs be strings?
Often yes when they are identifiers rather than quantities, particularly if leading zeros or very large values must be preserved.
Can pretty-printing change a large number?
The whitespace operation should not, but a parse-and-serialize formatter can emit a rounded value if the parser already lost precision.