← All JSON guides

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.

By JSON HearthPublished 2026-08-22

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

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.