30 aprile 2022

Metodi JSON, toJSON

Ipotizziamo di avere un oggetto complesso, che vogliamo convertire a stringa prima trasmetterlo in rete, o anche solo per mostrarlo sullo schermo.

Naturalmente, una stringa di questo tipo deve includere tutte le proprietà importanti.

Potremmo implementarla in questo modo:

let user = {
  name: "John",
  age: 30,

  toString() {
    return `{name: "${this.name}", age: ${this.age}}`;
  }
};

alert(user); // {name: "John", age: 30}

…Ma nel processo di sviluppo, potrebbero essere aggiunte/eliminate/rinominate nuove proprietà. Aggiornare costantemente la funzione toString non è una buona soluzione. Potremmo provare a iterare sulle proprietà dell’oggetto, ma cosa succederebbe se l’oggetto contenesse oggetti annidati? Dovremmo implementare anche questa conversione. E se dovessimo inviare l’oggetto in rete, dovremmo anche fornire il codice per poterlo “leggere”.

Fortunatamente, non c’è bisogno di scrivere del codice per gestire questa situazione.

JSON.stringify

JSON (JavaScript Object Notation) è un formato per rappresentare valori e oggetti. Viene descritto nello standard RFC 4627. Inizialmente fu creato per lavorare con JavaScript, ma molti altri linguaggi possiedono delle librerie per la sua gestione. Quindi JSON risulta semplice da usare per lo scambio di dati quando il client utilizza JavaScript e il server codifica in Ruby/PHP/Java/Altro.

JavaScript fornisce i metodi:

  • JSON.stringify per convertire oggetti in JSON.
  • JSON.parse per convertire JSON in oggetto.

Ad esempio, abbiamo JSON.stringify per uno studente:

let student = {
  name: 'John',
  age: 30,
  isAdmin: false,
  courses: ['html', 'css', 'js'],
  wife: null
};

let json = JSON.stringify(student);

alert(typeof json); //abbiamo una stringa!

alert(json);
/* JSON-encoded object:
{
  "name": "John",
  "age": 30,
  "isAdmin": false,
  "courses": ["html", "css", "js"],
  "wife": null
}
*/

Il metodo JSON.stringify(student) prende l’oggetto e lo converte in stringa.

La stringa json risultante viene chiamata codifica in JSON o serializzata, stringhificata, o addirittura oggetto caramellizzato. Ora è pronto per essere inviato o memorizzato.

Da notare che un oggetto codificato in JSON possiede delle fondamentali differenze da un oggetto letterale:

  • Le stringhe utilizzano doppie virgolette. In JSON non vengono utilizzare backtick o singole virgolette. Quindi 'John' diventa "John".
  • Anche i nomi delle proprietà dell’oggetto vengono racchiusi tra doppie virgolette. Quindi age:30 diventa "age":30.

JSON.stringify può anche essere applicato agli oggetti primitivi.

I tipi che supportano nativamente JSON sono:

  • Objects { ... }
  • Arrays [ ... ]
  • Primitives:
    • strings,
    • numbers,
    • valori boolean true/false,
    • null.

Ad esempio:

// un numero in JSON è solo un numero
alert( JSON.stringify(1) ) // 1

// una stringa in JSON è ancora una stringa, ma con doppie virgolette

alert( JSON.stringify('test') ) // "test"

alert( JSON.stringify(true) ); // true

alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]

JSON è un linguaggio specifico per i dati, quindi alcune proprietà specifiche di JavaScript vengono ignorate da JSON.stringify.

Tra cui:

  • Funzioni (metodi).
  • Proprietà di tipo symbol.
  • Proprietà che contengono undefined.
let user = {
  sayHi() { // ignorato
    alert("Hello");
  },
  [Symbol("id")]: 123, // ignorato
  something: undefined // ignorato
};

alert( JSON.stringify(user) ); // {} (oggetto vuoto)

Solitamente questo è ciò che vogliamo. Se invece abbiamo intenzioni diverse, molto presto vedremo come controllare il processo.

Un’ottima cosa è che anche gli oggetti annidati vengono automaticamente convertiti.

Ad esempio:

let meetup = {
  title: "Conference",
  room: {
    number: 23,
    participants: ["john", "ann"]
  }
};

alert( JSON.stringify(meetup) );
/* Tutta la struttura viene serializzata

{
  "title":"Conference",
  "room":{"number":23,"participants":["john","ann"]},
}
*/