JSON Number Precision Checker
JSON has one number type and no size limit; JavaScript parses it into a double. Above 253 the digits stop being exact, so a Twitter-style 64-bit id or a Postgres bigint comes back quietly wrong — 9007199254740993 becomes 9007199254740992, with no error anywhere. This scans the raw text before any parsing and shows you exactly which literals do not survive the round trip.
What "lossy" means here
A literal is lossy if String(Number(literal)) is not the literal back again. Two families fail
that test. Integers above Number.MAX_SAFE_INTEGER (9,007,199,254,740,991) land on
the nearest representable double, so consecutive ids can collapse onto the same value — the classic symptom is
two different records comparing equal. Decimals with more significant digits than a double carries
(about 17) are silently rounded, which matters for money, coordinates and scientific data.
The scan reads the raw text with a regular expression rather than parsing first, because parsing is precisely what destroys the evidence. Each finding shows the line, the literal as written, and the value it becomes.
Quoting is a fix with a cost
The rewrite wraps offending literals in quotes so the digits survive as strings. That is the standard fix for
64-bit ids and the reason so many APIs return "id": "9007199254740993" — the identifier is not
really a number, it is an opaque token that happens to be digits, and nobody ever does arithmetic on it.
But it changes the type, and every consumer now has to parse it. Downstream code doing id === 123
will stop matching, and a JSON Schema declaring "type": "integer" will reject the document. Tick
only rewrite values beyond MAX_SAFE_INTEGER to leave lossy decimals alone, since those are usually
genuine measurements where a string would be worse than a rounded number.
The real fix is upstream: have the producer emit ids as strings. Where you control the consumer instead,
JavaScript's JSON.parse reviver plus BigInt, Python's json.loads(…,
parse_int=…), or Go's json.Decoder.UseNumber() all preserve the digits without changing the
wire format.
Privacy
Nothing is uploaded. The scan runs in this tab using your own browser's JavaScript engine — no server sees your data, and the page keeps working with the network disconnected.
FAQ
My document reports clean but I still see wrong values. Why?
Then the loss happened before the document reached you — the producer already parsed and re-serialised through a double. Check the value at its source; once the digits are gone, nothing downstream can recover them.
Is 1.0 reported as lossy?
No. 1.0 parses to 1 and re-serialises as 1, which is a formatting difference, not a value change — the number is exactly representable. Only literals whose value changes are reported.
Does it handle exponent notation?
Yes — 1.23e300 is scanned like any other literal, and is reported only if the round trip changes it. Very large exponents that overflow to Infinity are reported, since Infinity is not valid JSON and will fail to re-serialise.
What about numbers inside strings already?
Untouched. A quoted value is a string, JSON never parses it as a number, and there is nothing to lose. That is exactly the state the rewrite puts your risky literals into.