JSON & Carnet de Contacts

JSON.stringify(), JSON.parse(), récapitulatif de la semaine

CRUD complet en mémoire avec séparation données/opérations

Utilisez les flèches, cliquez ou glissez pour naviguer

Objectifs de la leçon

1. Comprendre le format JSON

Règles strictes et différences avec les objets JS

2. Utiliser JSON.stringify()

Sérialiser un objet en chaîne

3. Utiliser JSON.parse()

Désérialiser une chaîne JSON

4. Récapituler la semaine

Objets, méthodes, destructuring, référence vs valeur

5. Graine d'architecture

Séparer les données des opérations

Plan du cours

1

JSON : le format universel

API, fichiers, config - comprendre les règles strictes

2

JSON.stringify() et JSON.parse()

Sérialiser et désérialiser - le deep clone limité

3

Récap de la semaine

Objets, méthodes, destructuring, référence vs valeur

4

Graine d'architecture

Séparer les données des opérations - la base de Clean Architecture

5

Projet : Carnet de contacts

CRUD immutable avec séparation données/opérations

JSON

JavaScript Object Notation

Le format universel d'échange de données

API, fichiers de config, stockage local

JSON vs Objet JavaScript

Objet JavaScript

const user = {

name: "Alice",

age: 25,

isActive: true,

greet: function() {

return "Hello!"

}

};

Clés sans guillemets, fonctions OK

JSON valide

{

"name": "Alice",

"age": 25,

"isActive": true

}

Clés entre guillemets doubles, pas de fonctions

Les règles strictes du JSON

Types autorisés

string (guillemets doubles)

number

boolean (true/false)

null

array [...]

object {...}

Interdit

fonctions

undefined

commentaires

trailing commas

guillemets simples

Date, RegExp, Map, Set

Les clés DOIVENT être entre guillemets doubles : "key"

Exemples de JSON valides

// Un contact

{

"nom": "Marie Dupont",

"email": "[email protected]",

"tel": "0612345678"

}

// Une liste de contacts

[

{ "nom": "Alice" },

{ "nom": "Bob" }

]

JSON est un format texte - il peut être stocké dans un fichier, envoyé via HTTP, ou sauvegardé dans localStorage

JSON.stringify()

Sérialiser un objet en chaîne JSON

Objet JavaScript -> Chaîne JSON

Syntaxe de JSON.stringify()

const obj = { nom: "Alice", age: 25 };

const json = JSON.stringify(obj);

// Résultat : '{"nom":"Alice","age":25}'

Entrée

Un objet JavaScript

Sortie

Une chaîne de caractères JSON

Les fonctions sont ignorées lors de la sérialisation!

Formatage pour la lisibilité

const contact = {

nom: "Marie",

email: "[email protected]"

};

const json = JSON.stringify(contact, null, 2);

// Résultat formaté :

{

"nom": "Marie",

"email": "[email protected]"

}

Le 3ème argument (2) indique l'indentation

JSON.parse()

Désérialiser une chaîne JSON en objet

Chaîne JSON -> Objet JavaScript

Syntaxe de JSON.parse()

const json = '{"nom":"Alice","age":25}';

const obj = JSON.parse(json);

// obj.nom === "Alice"

Entrée

Une chaîne JSON valide

Sortie

Un objet JavaScript

JSON.parse() lance une erreur si le JSON est mal formé!

Technique de Deep Clone

const original = { a: 1, b: { c: 2 } };

const clone = JSON.parse(JSON.stringify(original));

// clone est une copie indépendante!

Avantages

Copie profonde automatique

Simple à écrire

Limitations

Perd les fonctions

Perd undefined, Date devient string

Pas de références circulaires

Récapitulatif de la semaine

Les concepts objets essentiels

Objets & Méthodes

Destructuring

Référence vs Valeur

Spread Operator

Objets et Méthodes

const contact = {

nom: "Alice",

email: "[email protected]",

afficher() {

return `${this.nom} - ${this.email}`;

}

};

Propriétés

Des données stockées

contact.nom, contact.email

Méthodes

Des fonctions dans l'objet

contact.afficher()

Destructuring

const contact = { nom: "Alice", email: "[email protected]", tel: "06..." };

// Extraire des propriétés

const { nom, email } = contact;

// Renommer

const { nom: nomComplet } = contact;

// Valeur par défaut

const { ville = "Paris" } = contact;

Destructuring = extraire rapidement des propriétés d'un objet

Référence vs Valeur

Types primitifs (valeur)

let a = 5;

let b = a;

b = 10;

// a vaut toujours 5

Copie indépendante

Objets (référence)

let obj1 = { x: 1 };

let obj2 = obj1;

obj2.x = 99;

// obj1.x vaut 99 aussi!

Même objet en mémoire

Les objets sont passés par référence - modifier l'un modifie l'autre!

Spread Operator (...)

const original = { a: 1, b: 2 };

// Shallow copy

const copie = { ...original };

// Ajouter/modifier des propriétés

const modifie = { ...original, c: 3, b: 99 };

Shallow copy = copie superficielle (les objets imbriqués restent partagés)

Graine d'Architecture

Séparer les données des opérations

La base de la Clean Architecture

Chaque fonction fait UN seul job

Pourquoi séparer données et opérations?

Mauvaise approche

let contacts = [];

// Variable globale

// Fonctions qui la modifient

Difficile à tester, imprévisible

Bonne approche

// Données passées en paramètre

function ajouter(liste, contact) {

return [...liste, contact];

}

Prévisible, testable, réutilisable

Fonction Pure = Prévisibilité

// Fonction pure : retourne une NOUVELLE liste

function ajouterContact(liste, nouveauContact) {

return [...liste, nouveauContact];

}

// Utilisation

const ancienneListe = [{ nom: "Alice" }];

const nouvelleListe = ajouterContact(ancienneListe, { nom: "Bob" });

// ancienneListe reste inchangée!

Immutable = on ne modifie jamais, on crée une nouvelle version

CRUD Immutable

Create

[...liste, nouveau]

Read

liste.find(c => c.id === id)

Update

liste.map(c => c.id === id ? {...c, ...data} : c)

Delete

liste.filter(c => c.id !== id)

Chaque opération retourne une NOUVELLE liste sans modifier l'originale

Projet : Carnet de Contacts

CRUD complet en mémoire

Séparation données / opérations

Architecture propre et testable

Structure du projet

Données (data.js)

// État initial

const initialContacts = [

{ id: 1, nom: "Alice", ... }

];

Opérations (operations.js)

function ajouter(liste, contact) {...}

function supprimer(liste, id) {...}

function modifier(liste, id, data) {...}

Séparation claire = code maintenable et testable

Create - Ajouter un contact

function ajouterContact(liste, contact) {

return [...liste, {

id: Date.now(), // ID unique

...contact

}];

}

Retourne une nouvelle liste avec le contact ajouté

L'originale reste inchangée

Read - Lire les contacts

// Lire tous les contacts

function listerContacts(liste) {

return liste;

}

// Trouver un contact par ID

function trouverContact(liste, id) {

return liste.find(c => c.id === id);

}

find() retourne le premier élément qui correspond

Update - Modifier un contact

function modifierContact(liste, id, nouvellesDonnees) {

return liste.map(contact =>

contact.id === id

? { ...contact, ...nouvellesDonnees }

: contact

);

}

map() crée un nouveau tableau avec les modifications

Spread pour fusionner les anciennes et nouvelles données

Delete - Supprimer un contact

function supprimerContact(liste, id) {

return liste.filter(contact => contact.id !== id);

}

filter() garde uniquement les éléments qui ne correspondent pas à l'ID

Utilisation complète

// État initial

let contacts = [];

// Ajouter

contacts = ajouterContact(contacts, { nom: "Alice", email: "[email protected]" });

// Modifier

const id = contacts[0].id;

contacts = modifierContact(contacts, id, { nom: "Alice Dupont" });

// Supprimer

contacts = supprimerContact(contacts, id);

On réassigne contacts avec le résultat de chaque opération

Pièges courants avec JSON

Trailing commas interdits

{ "nom": "Alice", }

{ "nom": "Alice" }

Pas de commentaires

{ "nom": "Alice" /* erreur */ }

JSON.parse() lance une erreur si mal formé

Prévoir un try/catch pour la production

Pièges courants - Architecture

Utiliser des variables globales

let contacts = [];

function ajouter(c) {

contacts.push(c);

}

Effets de bord imprévisibles

Passer par paramètre

function ajouter(liste, c) {

return [...liste, c];

}

Prévisible et testable

Insister sur le passage par paramètre - c'est la base de l'architecture propre!

Points clés à retenir

JSON = format strict (guillemets doubles, pas de fonctions)

JSON.parse(JSON.stringify(obj)) = deep clone (mais limité)

Séparer données/opérations = graine de Clean Architecture

Chaque fonction fait UN seul job et reçoit les données en paramètre

Ă€ retenir!

JSON

Format universel, règles strictes

Guillemets doubles obligatoires

stringify/parse

Sérialiser / Désérialiser

Technique de deep clone

Immutable

Ne jamais modifier l'original

Créer une nouvelle version

Fonctions pures

Un seul job

Données en paramètre

Exercices pratiques

1. Créer un contact

Utiliser ajouterContact() avec nom, email, téléphone

2. Lister et trouver

Afficher tous les contacts, puis trouver par ID

3. Modifier un email

Utiliser modifierContact() pour changer l'email

4. Supprimer et vérifier

Supprimer un contact et vérifier que la liste est mise à jour

Questions?

JSON et l'architecture propre sont les fondations du développement moderne

Prochain cours : Persistance avec localStorage