Perché gli interi grandi perdono precisione
In sintesi: Gli interi superiori a 2^53-1 perdono precisione in JSON.parse. Gli ID snowflake, i numeri d'ordine e i bigint dei database lo incontrano tutti, quindi conservali come stringhe dall'inizio alla fine.

In sintesi: tratta gli ID snowflake, i numeri d'ordine e le chiavi primarie bigint come stringhe attraverso serializzazione, trasporto e parsing; mantieni il tipo numerico solo quando il campo è dimostrato restare entro 2^53-1, e allora imponilo con un vincolo maximum nello Schema.
Perché il danno avviene durante il parsing, silenziosamente.
JSON.parse('{"id": 9007199254740993}');
// { id: 9007199254740992 }
La cifra mancante è sparita; non c'è nulla da recuperare.
Da dove viene 2^53
JavaScript ha un unico tipo numerico: IEEE 754 double precision, con 53 bit di significando (uno implicito, 52 espliciti). Gli interi esatti si fermano quindi a ±(2^53-1):
-9007199254740991 .. 9007199254740991
Oltre quella linea, i valori rappresentabili consecutivi sono distanti 2, 4, 8. 9007199254740993 è dispari, e a quella grandezza ogni valore rappresentabile è pari, quindi viene arrotondato a 9007199254740992.
Campi colpiti
| Campo | Cifre | Rischio |
|---|---|---|
| ID snowflake | 18–19 | Alto, le ultime cifre cambiano |
| Numeri d'ordine / di transazione | 16–20 | Alto |
| Chiavi primarie bigint del database | 19 | Alto |
| Denaro in unità minori | — | Basso |
| Timestamp in millisecondi | 13 | Sicuro |
Il filo conduttore: questi sono identificatori, non quantità. Un identificatore viene trasportato, mai addizionato o moltiplicato, quindi la stringa è il tipo corretto.
Quattro correzioni
Serializza come stringa. Il backend converte i campi bigint prima di scrivere la risposta. Semplice e durevole; documenta che questi campi sono stringhe.
Lascia che il serializzatore se ne occupi. ToStringSerializer di Jackson per Long, il tag json:",string" di Go. Stessa idea: tieni il valore fuori dal percorso numerico.
Analizza con supporto BigInt. json-bigint e librerie simili. Nota che BigInt non può mescolarsi con l'aritmetica di Number, e JSON.stringify lo rifiuta.
Vincola l'intervallo. Se il campo davvero non può superare 2^53, aggiungi maximum nello Schema così i dati fuori intervallo falliscono la validazione invece di fallire silenziosamente nel browser.
Come capire se hai questo bug
Prendi un ID nota e fagli un round-trip: serializza, trasmetti, analizza, confronta carattere per carattere. Oppure ispeziona il corpo grezzo della risposta — un numero di 19 cifre senza virgolette che arriva con le ultime cifre errate è quasi certamente una perdita al momento del parsing.
FAQ
Perché JSON.parse cambia le ultime cifre senza un errore?
JavaScript ha un unico tipo numerico, IEEE 754 double precision, quindi gli interi superiori a 2^53-1 possono solo cadere sul valore rappresentabile più vicino. JSON.parse lo tratta come una normale conversione numerica: non lancia né avvisa.
Come può il frontend mantenere intatti gli interi grandi?
Usa una libreria come json-bigint, perché JSON.parse non può farlo. Il costo è che BigInt non può mescolarsi con l'aritmetica di Number e JSON.stringify lo rifiuta, quindi anche il codice circostante deve cambiare.
La documentazione dell'API deve indicare che questi campi sono stringhe?
Sì. Serializzare in stringhe è la correzione più semplice e durevole, ma funziona solo se i consumatori trattano il valore come testo, quindi il tipo del campo deve essere scritto nel contratto API.