EPUB/PDF
FR
→ JavaScript le language → Types de données
13 novembre 2022
JSON methods, toJSON
Supposons que nous avons un objet complexe et que nous aimerions le convertir en chaîne, l’envoyer par le
réseau ou simplement le rendre (l’output) à des fins de journalisation.
Naturellement, une telle chaîne devrait inclure toutes les propriétés importantes.
Nous pourrions implémenter la conversion comme ceci:
1 let user = {
2 name: "John",
3 age: 30,
4
5 toString() {
6 return `{name: "${[Link]}", age: ${[Link]}}`;
7 }
8 };
9
10 alert(user); // {name: "John", age: 30}
… Mais au cours du développement, de nouvelles propriétés sont ajoutées, les anciennes propriétés sont
renommées et supprimées. Mettre à jour un tel toString à chaque fois peut devenir pénible. Nous pourrions
essayer de passer en boucle sur les propriétés qu’il contient, mais que se passe-t-il si l’objet est complexe et qu’il
contient des objets imbriqués ? Nous aurions également besoin de mettre en œuvre leur conversion.
Heureusement, il n’est pas nécessaire d’écrire le code pour gérer tout cela. La tâche a déjà été résolue.
[Link]
Le JSON (JavaScript Object Notation) est un format général pour représenter les valeurs et les objets. Il est décrit
comme tel dans le standard RFC 4627. Initialement, il était conçu pour JavaScript, mais de nombreux autres
langages disposent également de bibliothèques pour le gérer. Il est donc facile d’utiliser JSON pour l’échange de
données lorsque le client utilise JavaScript et que le serveur est écrit sur Ruby/PHP/Java et bien d’autres.
JavaScript fournit des méthodes:
● [Link] pour convertir des objets en JSON.
● [Link] pour reconvertir JSON en objet.
Par exemple, nous allons [Link] un student (etudiant):
1 let student = {
2 name: 'John',
3 age: 30,
4 isAdmin: false,
5 courses: ['html', 'css', 'js'],
6 spouse: null
7 };
8
9 let json = [Link](student);
10
11 alert(typeof json); // nous avons une string!
12
13 alert(json);
14 /* JSON-encoded object:
15 {
16 "name": "John",
17 "age": 30,
18 "isAdmin": false,
19 "courses": ["html", "css", "js"],
20 "spouse": null
21 }
22 */
La méthode [Link](student) prend l’objet et le convertit en une chaîne.
La chaine json résultante est appelé un objet JSON-encoded ou serialized ou stringified ou marshalled. Nous
sommes prêts à l’envoyer par le câble ou à le placer dans un simple stockage de données.
Veuillez noter qu’un objet JSON-encoded a plusieurs différences importantes par rapport au objet littéral :
● Les chaînes utilisent des guillemets doubles. Il n’y a pas de guillemets simples ni de backticks en JSON. Donc
'John' deviendra "John" .
● Les propriété d’objet sont également en guillemets doubles. C’est obligatoire. Donc age:30 deviendra
"age":30 .
[Link] peut aussi être appliqué aux primitives.
JSON prend en charge les types de données suivants :
● Objets { ... }
● Tableaux [ ... ]
● Primitives:
● chaînes,
● nombres,
● valeurs booléennes true/false ,
● null .
Par exemple :
1 // un nombre en JSON est juste un nombre
2 alert( [Link](1) ) // 1
3
4 // une chaîne en JSON est toujours une chaîne, mais entre guillemets
5 alert( [Link]('test') ) // "test"
6
7 alert( [Link](true) ); // true
8
9 alert( [Link]([1, 2, 3]) ); // [1,2,3]
JSON est une spécification indépendante du langage et ne contenant que des données. Par conséquent,
certaines propriétés d’objet spécifiques à JavaScript sont ignorées par [Link] .
À savoir:
● Propriétés de fonction (méthodes).
● Clés et valeurs symboliques.
● Propriétés qui stockent undefined .
1 let user = {
2 sayHi() { // ignorée
3 alert("Hello");
4 },
5 [Symbol("id")]: 123, // ignorée
6 something: undefined // ignorée
7 };
8
9 alert( [Link](user) ); // {} (objet vide)
D’habitude ça va. Si ce n’est pas ce que nous souhaitons, nous verrons bientôt comment personnaliser le
processus.
Le grand avantage est que les objets imbriqués sont pris en charge et convertis automatiquement.
Par exemple:
1 let meetup = {
2 title: "Conference",
3 room: {
4 number: 23,
5 participants: ["john", "ann"]
6 }
7 };
8
9 alert( [Link](meetup) );
10 /* La structure entière est stringified:
11 {
12 "title":"Conference",
13 "room":{"number":23,"participants":["john","ann"]},
14 }
15 */
La limitation importante: il ne doit pas y avoir de références circulaires.
Par exemple:
1 let room = {
2 number: 23
3 };
4
5 let meetup = {
6 title: "Conference",
7 participants: ["john", "ann"]
8 };
9
10 [Link] = room; // meetup references room
11 [Link] = meetup; // room references meetup
12
13 [Link](meetup); // Erreur: Conversion d'une structure circulaire en JSO
Ici, la conversion échoue à cause d’une référence circulaire: [Link] references meetup , et
[Link] references room :
number: 23
occupiedBy place
title: "Conference"
participants
...
Exclure et transformer: replacer
La syntaxe complète de [Link] est:
1 let json = [Link](value[, replacer, space])
Value
Une valeur à encoder.
Replacer
Tableau de propriétés à encoder ou une fonction de mapping function(key, value) .
Space
Quantité d’espace à utiliser pour le formatage
La plupart du temps, [Link] est utilisé avec le premier argument uniquement. Mais si nous devons
affiner le processus de remplacement, préférez filtrer les références circulaires, nous pouvons utiliser le deuxième
argument de [Link] .
Si nous lui passons un tableau de propriétés, seules ces propriétés seront encodées.
Par exemple:
1 let room = {
2 number: 23
3 };
4
5 let meetup = {
6 title: "Conference",
7 participants: [{name: "John"}, {name: "Alice"}],
8 place: room // meetup references room
9 };
10
11 [Link] = meetup; // room references meetup
12
13 alert( [Link](meetup, ['title', 'participants']) );
14 // {"title":"Conference","participants":[{},{}]}
Ici, nous sommes probablement trop strictes. La liste de propriétés est appliquée à la structure entière de l’objet.
Donc, les objets dans participants sont vides, parce que name n’est pas dans la liste.
Incluons dans la liste toutes les propriétés sauf [Link] qui provoquerait la référence circulaire :
1 let room = {
2 number: 23
3 };
4
5 let meetup = {
6 title: "Conference",
7 participants: [{name: "John"}, {name: "Alice"}],
8 place: room // meetup references room
9 };
10
11 [Link] = meetup; // room references meetup
12
13 alert( [Link](meetup, ['title', 'participants', 'place', 'name', 'numbe
14 /*
15 {
16 "title":"Conference",
17 "participants":[{"name":"John"},{"name":"Alice"}],
18 "place":{"number":23}
19 }
20 */
Maintenant tout sauf occupiedBy est serialized. Mais la liste des propriétés est assez longue.
Heureusement, nous pouvons utiliser une fonction au lieu d’un tableau comme replacer .
La fonction sera appelée pour chaque paire de (key, value) et devrait renvoyer la valeur “remplacée”, qui
sera utilisée à la place de celle d’origine. Ou undefined si la valeur doit être ignorée.
Dans notre cas, nous pouvons retourner une value “en l’état” pour tout sauf occupiedBy . Pour ignorer
occupiedBy , le code ci-dessous retourne undefined :
1 let room = {
2 number: 23
3 };
4
5 let meetup = {
6 title: "Conference",
7 participants: [{name: "John"}, {name: "Alice"}],
8 place: room // meetup references room
9 };
10
11 [Link] = meetup; // room references meetup
12
13 alert( [Link](meetup, function replacer(key, value) {
14 alert(`${key}: ${value}`);
15 return (key == 'occupiedBy') ? undefined : value;
16 }));
17
18 /* key:value pairs that come to replacer:
19 : [object Object]
20 title: Conference
21 participants: [object Object],[object Object]
22 0: [object Object]
23 name: John
24 1: [object Object]
25 name: Alice
26 place: [object Object]
27 number: 23
28 occupiedBy: [object Object]
29 */
Veuillez noter que la fonction replacer récupère chaque paire clé/valeur, y compris les objets imbriqués et les
éléments de tableau. Il est appliqué de manière récursive. La valeur this dans replacer est l’objet qui
contient la propriété actuelle.
Le premier appel est spécial. Il est fabriqué en utilisant un “objet wrapper” spécial: {"": meetup} . En d’autres
termes, la première paire (key, value) a une clé vide, et la valeur est l’objet cible dans son ensemble. C’est
pourquoi la première ligne est ":[object Object]" dans l’exemple ci-dessus.
L’idée est de fournir autant de puissance pour replacer que possible : il a une chance d’analyser et de
remplacer/ignorer même l’objet entier si nécessaire.
Formatage : space
Le troisième argument de [Link](value, replacer, space) est le nombre d’espaces à utiliser
pour un joli formatage.
Auparavant, tous les objets stringifiés n’avaient pas d’indentation ni d’espace supplémentaire. C’est bien si nous
voulons envoyer un objet sur un réseau. L’arguement space est utilisé exclusivement pour une belle sortie.
Ici space = 2 indique à JavaScript d’afficher des objets imbriqués sur plusieurs lignes, avec l’indentation de 2
espaces à l’intérieur d’un objet :
1 let user = {
2 name: "John",
3 age: 25,
4 roles: {
5 isAdmin: false,
6 isEditor: true
7 }
8 };
9
10 alert([Link](user, null, 2));
11 /* indentation de 2 espaces:
12 {
13 "name": "John",
14 "age": 25,
15 "roles": {
16 "isAdmin": false,
17 "isEditor": true
18 }
19 }
20 */
21
22 /* pour [Link](user, null, 4) le résultat serait plus indenté:
23 {
24 "name": "John",
25 "age": 25,
26 "roles": {
27 "isAdmin": false,
28 "isEditor": true
29 }
30 }
31 */
Le troisième argument peut également être une chaîne de caractères. Dans ce cas, la chaîne de caractères est
utilisée pour l’indentation au lieu d’un certain nombre d’espaces.
Le paramètre space est utilisé uniquement à des fins de journalisation et de sortie agréable.
“toJSON” Personnalisé
Comme toString pour la conversion de chaîne, un objet peut fournir une méthode toJSON pour une
conversion en JSON. [Link] appelle automatiquement si il est disponible.
Par exemple:
1 let room = {
2 number: 23
3 };
4
5 let meetup = {
6 title: "Conference",
7 date: new Date([Link](2017, 0, 1)),
8 room
9 };
10
11 alert( [Link](meetup) );
12 /*
13 {
14 "title":"Conference",
15 "date":"2017-01-01T[Link].000Z", // (1)
16 "room": {"number":23} // (2)
17 }
18 */
Ici on peut voir que date (1) est devenu une chaîne. C’est parce que toutes les dates ont une méthode
toJSON intégrée qui retourne ce genre de chaîne.
Ajoutons maintenant un toJSON personnalisé pour notre objet room (2) :
1 let room = {
2 number: 23,
3 toJSON() {
4 return [Link];
5 }
6 };
7
8 let meetup = {
9 title: "Conference",
10 room
11 };
12
13 alert( [Link](room) ); // 23
14
15 alert( [Link](meetup) );
16 /*
17 {
18 "title":"Conference",
19 "room": 23
20 }
21 */
Comme on peut le voir, toJSON est utilisé à la fois pour l’appel direct [Link](room) et quand
room est imbriqué dans un autre objet encodé.
[Link]
Pour décoder une chaîne JSON, nous avons besoin d’une autre méthode nommée [Link].
La syntaxe:
1 let value = [Link](str, [reviver]);
str
La chaîne JSON à parse.
reviver
Fonction optionnelle (clé,valeur) qui sera appelée pour chaque paire (key, value) et peut transformer la
valeur.
Par exemple:
1 // stringified array
2 let numbers = "[0, 1, 2, 3]";
3
4 numbers = [Link](numbers);
5
6 alert( numbers[1] ); // 1
Ou pour les objets imbriqués:
1 let userData = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,
2
3 let user = [Link](userData);
4
5 alert( [Link][1] ); // 1
Le JSON peut être aussi complexe que nécessaire, les objets et les tableaux peuvent inclure d’autres objets et
tableaux. Mais ils doivent obéir au même format JSON.
Voici des erreurs typiques dans JSON écrit à la main (nous devons parfois l’écrire à des fins de débogage):
1 let json = `{
2 name: "John", // Erreur: nom de propriété sans guillemets
3 "surname": 'Smith', // Erreur: guillemets simples en valeur (do
4 'isAdmin': false // Erreur: guillemets simples dans la clé
5 "birthday": new Date(2000, 2, 3), // Erreur: aucun "nouveau" n'est autorisé,
6 "friends": [0,1,2,3] // Ici tout va bien
7 }`;
En outre, JSON ne prend pas en charge les commentaires. L’ajout d’un commentaire à JSON le rend invalide.
Il y a un autre format nommé JSON5,qui autorise les clés non commentées, les commentaires, etc. Mais il s’agit
d’une bibliothèque autonome, pas dans la spécification du langage.
Le JSON standard est très strict, non pas parce que ses développeurs sont paresseux, mais pour permettre une
implémentation facile, fiable et très rapide de l’algorithme de conversion.
Utiliser Reviver
Imaginez, nous avons un objet stringified meetup sur le serveur.
Cela ressemble à ça:
1 // title: (meetup title), date: (meetup date)
2 let str = '{"title":"Conference","date":"2017-11-30T[Link].000Z"}';
… Et maintenant, nous devons le deserialize, pour le retourner en objet JavaScript.
Faisons-le en appelant [Link] :
1 let str = '{"title":"Conference","date":"2017-11-30T[Link].000Z"}';
2
3 let meetup = [Link](str);
4
5 alert( [Link]() ); // Error!
Whoops! Une erreur!
La valeur de [Link] est une chaîne, pour un objet Date .Comment [Link] pourrait-il savoir qu’il
devrait transformer cette chaîne en Date ?
Passons à [Link] la fonction de réactivation en tant que second argument, qui renvoie toutes les valeurs
“en l’état”, mais date deviendra une Date :
1 let str = '{"title":"Conference","date":"2017-11-30T[Link].000Z"}';
2
3 let meetup = [Link](str, function(key, value) {
4 if (key == 'date') return new Date(value);
5 return value;
6 });
7
8 alert( [Link]() ); // ça fonctionne maintenant!
À propos, cela fonctionne aussi pour les objets imbriqués:
1 let schedule = `{
2 "meetups": [
3 {"title":"Conference","date":"2017-11-30T[Link].000Z"},
4 {"title":"Birthday","date":"2017-04-18T[Link].000Z"}
5 ]
6 }`;
7
8 schedule = [Link](schedule, function(key, value) {
9 if (key == 'date') return new Date(value);
10 return value;
11 });
12
13 alert( [Link][1].[Link]() ); // ça fonctionne!
Résumé
● JSON est un format de données qui possède son propre standard indépendant et ses propres bibliothèques
pour la plupart des langages de programmation.
● JSON prend en charge les objets simples, les tableaux, les chaînes, les nombres, les booléens et null .
● JavaScript fournit des méthodes [Link] pour sérialiser en JSON et [Link] pour lire depuis JSON.
● Les deux méthodes prennent en charge les fonctions du transformateur pour une lecture/écriture intelligente.
● Si un objet a toJSON , alors il est appelé par [Link] .
Exercices
Transforme l'objet en JSON et revenez en arrière
importance: 5
Transformez l’utilisateur en JSON puis relisez-le dans une autre variable.
1 let user = {
2 name: "John Smith",
3 age: 35
4 };
solution
Exclure les backreferences
importance: 5
Dans les cas simples de références circulaires, nous pouvons exclure une propriété incriminée de la sérialisation
par son nom.
Mais parfois, nous ne pouvons pas simplement utiliser le nom, car il peut être utilisé à la fois dans les références
circulaires et dans les propriétés normales. Ainsi, nous pouvons vérifier la propriété par sa valeur.
Écrivez la fonction de remplacement pour tout stringify, mais supprimez les propriétés qui font référence à
meetup :
1 let room = {
2 number: 23
3 };
4
5 let meetup = {
6 title: "Conference",
7 occupiedBy: [{name: "John"}, {name: "Alice"}],
8 place: room
9 };
10
11 // circular references
12 [Link] = meetup;
13 [Link] = meetup;
14
15 alert( [Link](meetup, function replacer(key, value) {
16 /* your code */
17 }));
18
19 /* result should be:
20 {
21 "title":"Conference",
22 "occupiedBy":[{"name":"John"},{"name":"Alice"}],
23 "place":{"number":23}
24 }
25 */
solution
Cours précédent Prochain cours
Partager Carte du tutoriel
Commentaires
● Si vous avez des améliorations à suggérer, merci de soumettre une issue GitHub ou une pull request
au lieu de commenter.
● Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.
● Pour insérer quelques bouts de code, utilisez la balise <code> , pour plusieurs lignes – enveloppez-les
avec la balise <pre> , pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen…)
© 2007—2023 Ilya Kantorà propos du projet
nous contacter