← Tutti gli articoli

Come serializzare JSON con JSON.stringify

JSON.stringify converte un valore in stringa JSON. Impara gli argomenti space e replacer, l'hook toJSON e i valori che scarta silenziosamente o su cui solleva.

JSON.stringify() converte un valore JavaScript in una stringa JSON —— per inviarlo nel body di una richiesta, salvarlo in un file o riporlo in localStorage. Sembra semplice, ma i suoi tre argomenti, la gestione dei valori speciali e l'hook toJSON fanno inciampare gli sviluppatori in continuazione. Questa guida copre tutto ciò che fa JSON.stringify(), gli equivalenti in altri linguaggi e le trappole da evitare.

Cosa fa JSON.stringify

Percorre un valore in modo ricorsivo e produce una stringa JSON conforme alla spec. L'output di default è compatto, senza spazi extra:

const user = { name: "Ada", age: 36, active: true };

JSON.stringify(user);
// '{"name":"Ada","age":36,"active":true}'

Poiché emette sempre JSON valido, non costruire mai stringhe JSON a mano con concatenazione o template literal —— farlo è la causa numero uno di errori [object Object] e errori di virgole finali.

I tre argomenti

JSON.stringify(value, replacer, space) accetta un valore più due argomenti opzionali che quasi nessuno usa —— ma sono potenti.

space —— pretty-print

Il terzo argomento controlla l'indentazione. Passa un numero per quegli spazi, o una stringa come '\t' per tabulazioni:

JSON.stringify(user, null, 2);
// {
//   "name": "Ada",
//   "age": 36,
//   "active": true
// }

È così che si fa pretty-print di JSON nel codice —— vedi Come formattare JSON. Ometti l'argomento (o passa 0) per minificare; vedi Come minificare JSON.

replacer —— filtrare e trasformare

Il secondo argomento può essere un array di chiavi da includere o una funzione che trasforma ogni valore:

// Whitelist: solo queste chiavi sopravvivono
JSON.stringify(user, ['name', 'active']);
// '{"name":"Ada","active":true}'

// Funzione: maschera un campo, scarta un altro
JSON.stringify(
  { name: "Ada", password: "secret", token: "abc" },
  (key, value) => {
    if (key === 'password') return '[REDACTED]';
    if (key === 'token') return undefined; // restituire undefined omette la chiave
    return value;
  },
);
// '{"name":"Ada","password":"[REDACTED]"}'

L'hook toJSON

Se un valore ha un metodo toJSON(), JSON.stringify() lo chiama e serializza al suo posto il valore restituito. È così che gli oggetti Date diventano automaticamente stringhe ISO:

JSON.stringify({ when: new Date('2026-05-24T00:00:00Z') });
// '{"when":"2026-05-24T00:00:00.000Z"}'  ← Date.prototype.toJSON eseguito

// Definisci il tuo toJSON per serializzazione custom
class Money {
  constructor(cents) { this.cents = cents; }
  toJSON() { return (this.cents / 100).toFixed(2); }
}
JSON.stringify({ price: new Money(1999) });
// '{"price":"19.99"}'

Cosa viene scartato o convertito

JSON ha solo sei tipi, quindi i valori JavaScript senza equivalente JSON vengono silenziosamente scartati o convertiti —— fonte comune di bug nei round-trip:

Valore JavaScriptRisultato di JSON.stringify
undefined (in oggetto)chiave omessa
undefined (in array)null
funzioneomessa (oggetto) / null (array)
Symbolomesso
NaN, Infinitynull
Datestringa ISO (via toJSON)
BigIntlancia TypeError

Per l'elenco completo di come JSON differisce dagli oggetti JavaScript, vedi JSON vs oggetti JavaScript.

Trappole comuni

I riferimenti circolari lanciano

const a = {};
a.self = a;
JSON.stringify(a);
// TypeError: Converting circular structure to JSON

// Correzione: un replacer che traccia oggetti visti, o ristruttura i dati

BigInt non è supportato

JSON.stringify({ id: 9007199254740993n });
// TypeError: Do not know how to serialize a BigInt

// Correzione: converti in stringa prima, o aggiungi un replacer
JSON.stringify({ id: 9007199254740993n }, (k, v) =>
  typeof v === 'bigint' ? v.toString() : v
);

Gli interi grandi perdono precisione nel round-trip

I numeri oltre 253 non possono essere rappresentati esattamente. Se fai stringify e poi parse di un ID intero grande, può cambiare. Conserva tali ID come stringhe.

API vicine: structuredClone, il reviver e Stable Stringify

  • structuredClone —— per copie profonde in memoria, non usare JSON.parse(JSON.stringify(x)). structuredClone gestisce Date, Map, Set, ArrayBuffer e riferimenti circolari in modo nativo ed è molto più veloce.
  • L'argomento reviver di JSON.parse è lo specchio del replacer di qui. Usali in coppia per round-trip senza perdita su tipi che JSON non modella —— es. codifica Date come stringa ISO nel replacer e reidratala nel reviver.
  • Librerie di stable-stringify (es. json-stable-stringify, fast-json-stable-stringify) —— producono la stessa stringa indipendentemente dall'ordine di inserimento delle chiavi. Usale quando l'output viene hashato, firmato o confrontato come testo (vedi RFC 8785 / JCS per la versione formale).

Stringify in altri linguaggi

# Python
import json
json.dumps({"name": "Ada"})                       # compatto
json.dumps({"name": "Ada"}, indent=2)             # pretty
json.dumps({"name": "Ada"}, separators=(',', ':')) # minificato

// Go
import "encoding/json"
b, _ := json.Marshal(map[string]string{"name": "Ada"})

// Ruby
require 'json'
{ name: "Ada" }.to_json

Stringify di JSON nel tuo browser

Devi fare escape di un valore JSON in un literal di stringa —— per incorporarlo in codice, in una colonna di DB o in un comando shell? Lo strumento JSON Stringify di fixjson lo fa all'istante, nel tuo browser, senza inviare dati a nessun server.

Domande frequenti

Come faccio pretty-print con JSON.stringify?

Passa un terzo argomento: JSON.stringify(value, null, 2) per 2 spazi o '\t' per tabulazioni. Vedi Come formattare JSON.

Perché JSON.stringify scarta alcune delle mie proprietà?

Le proprietà con valori undefined, funzione o Symbol vengono omesse perché JSON non ha rappresentazione per loro. Usa un replacer o convertile prima.

Come faccio stringify di un valore con BigInt?

JSON.stringify() lancia su BigInt. Fornisci un replacer che chiami .toString() sui bigint e parsali deliberatamente dall'altra parte.

Qual è la differenza tra JSON.stringify e JSON.parse?

stringify trasforma un valore in una stringa JSON; parse trasforma una stringa JSON in un valore. Sono inversi. Per le trappole del parsing, vedi Gestire JSON rotto in JavaScript.

Come faccio JSON.stringify di un Map o Set?

Di default entrambi serializzano come "{}" —— una Map non ha proprietà proprie enumerabili e un Set stringifica come oggetto vuoto. Convertili prima in una forma JSON-friendly (o tramite un replacer):

// Map → array di coppie [key, value] (round-trippable)
JSON.stringify([...myMap]);
// o con un replacer:
JSON.stringify({ data: myMap }, (k, v) =>
  v instanceof Map ? Object.fromEntries(v) :
  v instanceof Set ? [...v] : v
);

Sulla strada del ritorno, ricostruisci con new Map(arr) / new Set(arr) in un reviver di JSON.parse, dato che il JSON puro non ha tipi Map/Set.

Provalo ora