Ricerca…
introduzione
JSON (JavaScript Object Notation) è un leggero formato di scambio di dati. È facile per gli esseri umani leggere e scrivere e facile per le macchine analizzare e generare. È importante rendersi conto che, in JavaScript, JSON è una stringa e non un oggetto.
Una panoramica di base può essere trovata sul sito web json.org che contiene anche collegamenti alle implementazioni dello standard in molti diversi linguaggi di programmazione.
Sintassi
- JSON.parse (input [, reviver])
- JSON.stringify (valore [, replacer [, spazio]])
Parametri
Parametro | Dettagli |
---|---|
JSON.parse | Analizza una stringa JSON |
input(string) | Stringa JSON da analizzare. |
reviver(function) | Prescrive una trasformazione per la stringa JSON di input. |
JSON.stringify | Serializzare un valore serializzabile |
value(string) | Valore da serializzare in base alle specifiche JSON. |
replacer(function o String[] o Number[]) | Seleziona in modo selettivo alcune proprietà dell'oggetto value . |
space(String o Number ) | Se un number viene fornito, space numero di spazi vuoti verrà inserito di leggibilità. Se viene fornita una string , la stringa (primi 10 caratteri) verrà utilizzata come spazi vuoti. |
Osservazioni
I metodi di utilità JSON sono stati prima standardizzati in ECMAScript 5.1 §15.12 .
Il formato è stato formalmente definito in L'applicazione / json Media Type per JSON (RFC 4627 luglio 2006) che è stata successivamente aggiornata in JSON Data Interchange Format (RFC 7158 marzo 2013, ECMA-404 ottobre 2013 e RFC 7159 marzo 2014).
Per rendere disponibili questi metodi nei vecchi browser come Internet Explorer 8, utilizzare json2.js di Douglas Crockford.
Analisi di una semplice stringa JSON
Il metodo JSON.parse()
analizza una stringa come JSON e restituisce una primitiva, un array o un oggetto JavaScript:
const array = JSON.parse('[1, 2, "c", "d", {"e": false}]');
console.log(array); // logs: [1, 2, "c", "d", {e: false}]
Serializzare un valore
Un valore JavaScript può essere convertito in una stringa JSON utilizzando la funzione JSON.stringify
.
JSON.stringify(value[, replacer[, space]])
-
value
Il valore da convertire in una stringa JSON.
/* Boolean */ JSON.stringify(true) // 'true'
/* Number */ JSON.stringify(12) // '12'
/* String */ JSON.stringify('foo') // '"foo"'
/* Object */ JSON.stringify({}) // '{}'
JSON.stringify({foo: 'baz'}) // '{"foo": "baz"}'
/* Array */ JSON.stringify([1, true, 'foo']) // '[1, true, "foo"]'
/* Date */ JSON.stringify(new Date()) // '"2016-08-06T17:25:23.588Z"'
/* Symbol */ JSON.stringify({x:Symbol()}) // '{}'
-
replacer
Una funzione che altera il comportamento del processo di stringificazione o una matrice di oggetti String e Number che fungono da whitelist per filtrare le proprietà dell'oggetto value da includere nella stringa JSON. Se questo valore è nullo o non viene fornito, tutte le proprietà dell'oggetto sono incluse nella stringa JSON risultante.
// replacer as a function
function replacer (key, value) {
// Filtering out properties
if (typeof value === "string") {
return
}
return value
}
var foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 }
JSON.stringify(foo, replacer)
// -> '{"week": 45, "month": 7}'
// replacer as an array
JSON.stringify(foo, ['foundation', 'week', 'month'])
// -> '{"foundation": "Mozilla", "week": 45, "month": 7}'
// only the `foundation`, `week`, and `month` properties are kept
-
space
Per la leggibilità, il numero di spazi utilizzati per il rientro può essere specificato come terzo parametro.
JSON.stringify({x: 1, y: 1}, null, 2) // 2 space characters will be used for indentation
/* output:
{
'x': 1,
'y': 1
}
*/
In alternativa, è possibile fornire un valore stringa da utilizzare per il rientro. Ad esempio, il passaggio di '\t'
causerà l'uso del carattere di tabulazione per il rientro.
JSON.stringify({x: 1, y: 1}, null, '\t')
/* output:
{
'x': 1,
'y': 1
}
*/
Serializzazione con una funzione di sostituzione
Una funzione di replacer
può essere utilizzata per filtrare o trasformare i valori che vengono serializzati.
const userRecords = [
{name: "Joe", points: 14.9, level: 31.5},
{name: "Jane", points: 35.5, level: 74.4},
{name: "Jacob", points: 18.5, level: 41.2},
{name: "Jessie", points: 15.1, level: 28.1},
];
// Remove names and round numbers to integers to anonymize records before sharing
const anonymousReport = JSON.stringify(userRecords, (key, value) =>
key === 'name'
? undefined
: (typeof value === 'number' ? Math.floor(value) : value)
);
Questo produce la seguente stringa:
'[{"points":14,"level":31},{"points":35,"level":74},{"points":18,"level":41},{"points":15,"level":28}]'
Parsing con una funzione Reviver
Una funzione reviver può essere utilizzata per filtrare o trasformare il valore che viene analizzato.
var jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';
var data = JSON.parse(jsonString, function reviver(key, value) {
return key === 'name' ? value.toUpperCase() : value;
});
const jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';
const data = JSON.parse(jsonString, (key, value) =>
key === 'name' ? value.toUpperCase() : value
);
Questo produce il seguente risultato:
[
{
'name': 'JOHN',
'score': 51
},
{
'name': 'JACK',
'score': 17
}
]
Ciò è particolarmente utile quando devono essere inviati dati che devono essere serializzati / codificati quando vengono trasmessi con JSON, ma si vuole accedervi deserializzati / decodificati. Nell'esempio seguente, una data è stata codificata nella sua rappresentazione ISO 8601. Usiamo la funzione Reviver per analizzarla in una Date
JavaScript.
var jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';
var data = JSON.parse(jsonString, function (key, value) {
return (key === 'date') ? new Date(value) : value;
});
const jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';
const data = JSON.parse(jsonString, (key, value) =>
key === 'date' ? new Date(value) : value
);
È importante assicurarsi che la funzione Reviver restituisca un valore utile alla fine di ogni iterazione. Se la funzione reviver undefined
viene undefined
, nessun valore o l'esecuzione si interrompe verso la fine della funzione, la proprietà viene cancellata dall'oggetto. In caso contrario, la proprietà viene ridefinita come il valore restituito.
Serializzazione e ripristino di istanze di classe
È possibile utilizzare un metodo toJSON
personalizzato e la funzione reviver per trasmettere istanze della propria classe in JSON. Se un oggetto ha un metodo toJSON
, il suo risultato sarà serializzato anziché l'oggetto stesso.
function Car(color, speed) {
this.color = color;
this.speed = speed;
}
Car.prototype.toJSON = function() {
return {
$type: 'com.example.Car',
color: this.color,
speed: this.speed
};
};
Car.fromJSON = function(data) {
return new Car(data.color, data.speed);
};
class Car {
constructor(color, speed) {
this.color = color;
this.speed = speed;
this.id_ = Math.random();
}
toJSON() {
return {
$type: 'com.example.Car',
color: this.color,
speed: this.speed
};
}
static fromJSON(data) {
return new Car(data.color, data.speed);
}
}
var userJson = JSON.stringify({
name: "John",
car: new Car('red', 'fast')
});
Questo produce una stringa con il seguente contenuto:
{"name":"John","car":{"$type":"com.example.Car","color":"red","speed":"fast"}}
var userObject = JSON.parse(userJson, function reviver(key, value) {
return (value && value.$type === 'com.example.Car') ? Car.fromJSON(value) : value;
});
Questo produce il seguente oggetto:
{
name: "John",
car: Car {
color: "red",
speed: "fast",
id_: 0.19349242527065402
}
}
JSON contro i letterali JavaScript
JSON sta per "JavaScript Object Notation", ma non è JavaScript. Pensate a come solo un formato di serializzazione dei dati che sembra essere direttamente utilizzabile come un letterale JavaScript. Tuttavia, non è consigliabile eseguire direttamente (cioè attraverso eval()
) JSON che viene recuperato da una fonte esterna. Funzionalmente, JSON non è molto diverso da XML o YAML - una certa confusione può essere evitata se JSON è solo immaginato come un formato di serializzazione che assomiglia molto a JavaScript.
Anche se il nome implica solo oggetti, e anche se la maggior parte dei casi d'uso attraverso una sorta di API è sempre rappresentata da oggetti e matrici, JSON non è solo per oggetti o matrici. Sono supportati i seguenti tipi primitivi:
- String (es.
"Hello World!"
) - Numero (es.
42
) - Booleano (es.
true
) - Il valore
null
undefined
non è supportato nel senso che una proprietà non definita verrà omessa da JSON su serializzazione. Pertanto, non è possibile deserializzare JSON e finire con una proprietà il cui valore undefined
è undefined
.
La stringa "42"
è JSON valida. JSON non deve sempre avere una busta esterna di "{...}"
o "[...]"
.
Mentre nome JSON è anche JavaScript valido e JavaScript è anche JSON valido, ci sono alcune sottili differenze tra le due lingue e nessuna delle due lingue è un sottoinsieme dell'altro.
Prendi la seguente stringa JSON come esempio:
{"color": "blue"}
Questo può essere inserito direttamente in JavaScript. Sarà sintatticamente valido e produrrà il valore corretto:
const skin = {"color": "blue"};
Tuttavia, sappiamo che "color" è un nome identificativo valido e le virgolette intorno al nome della proprietà possono essere omesse:
const skin = {color: "blue"};
Sappiamo anche che possiamo usare le virgolette singole invece delle doppie virgolette:
const skin = {'color': 'blue'};
Ma, se dovessimo prendere entrambi questi letterali e trattarli come JSON, nessuno dei due sarà JSON sintatticamente valido :
{color: "blue"}
{'color': 'blue'}
JSON richiede rigorosamente che tutti i nomi delle proprietà siano tra virgolette e anche i valori delle stringhe siano tra virgolette.
È normale che i nuovi arrivati di JSON tentano di utilizzare estratti di codice con JavaScript letterali come JSON e si scervellano sugli errori di sintassi che ricevono dal parser JSON.
Comincia più confusione quando viene applicata una terminologia errata nel codice o nella conversazione.
Un anti-pattern comune è il nome di variabili che contengono valori non JSON come "json":
fetch(url).then(function (response) {
const json = JSON.parse(response.data); // Confusion ensues!
// We're done with the notion of "JSON" at this point,
// but the concept stuck with the variable name.
});
Nell'esempio precedente, response.data
è una stringa JSON restituita da alcune API. JSON si arresta nel dominio di risposta HTTP. La variabile con il termine improprio "json" contiene solo un valore JavaScript (potrebbe essere un oggetto, un array o anche un semplice numero!)
Un modo meno confusionario per scrivere quanto sopra è:
fetch(url).then(function (response) {
const value = JSON.parse(response.data);
// We're done with the notion of "JSON" at this point.
// You don't talk about JSON after parsing JSON.
});
Gli sviluppatori tendono anche a lanciare la frase "oggetto JSON" molto spesso. Questo porta anche alla confusione. Perché come accennato in precedenza, una stringa JSON non deve contenere un oggetto come valore. "JSON string" è un termine migliore. Proprio come "stringa XML" o "stringa YAML". Ottieni una stringa, la analizzi e ottieni un valore.
Valori di oggetti ciclici
Non tutti gli oggetti possono essere convertiti in una stringa JSON. Quando un oggetto ha riferimenti auto ciclici, la conversione fallirà.
Questo è in genere il caso delle strutture di dati gerarchici in cui genitori e figli si riferiscono entrambi l'un l'altro:
const world = {
name: 'World',
regions: []
};
world.regions.push({
name: 'North America',
parent: 'America'
});
console.log(JSON.stringify(world));
// {"name":"World","regions":[{"name":"North America","parent":"America"}]}
world.regions.push({
name: 'Asia',
parent: world
});
console.log(JSON.stringify(world));
// Uncaught TypeError: Converting circular structure to JSON
Non appena il processo rileva un ciclo, viene sollevata l'eccezione. Se non ci fosse il rilevamento del ciclo, la stringa sarebbe infinitamente lunga.