Pourquoi JSON : guide complet ?
Contexte réel : pourquoi un dev a besoin de ce au quotidien JSON est l'un des formats les plus utilisés pour la communication entre clients et serveurs sur Internet. Il est utilisé dans de nombreux cas tels que les requêtes API, le stockage de données sur les appareils mobiles et l'échange de données en temps réel.
Un cas d'usage concret en 2-3 phrases Imaginez que vous travaillez pour une application de gestion de tâches. Vous avez besoin d'un moyen simple et efficace de stocker, récupérer et partager les informations sur les tâches entre le frontend et le backend. JSON est parfaitement adapté à ce cas car il permet de représenter des données complexes sous forme de structures simples et faciles à lire.
Prerequis
- Connaissances de base en programmation (JavaScript recommandé)
- Un éditeur de texte ou un IDE (CodePen, VS Code, etc.)
- Node.js installé sur votre machine (version 14.0.0 ou plus tard)
Pour installer Node.js, rendez-vous sur le site officiel Node.js et téléchargez la version recommandée.
Concepts fondamentaux
Structure de base
La structure de base d'un objet JSON est une paire clé-valeur. Voici un exemple :
{
"nom": "John",
"age": 30,
"est_majeur": true
}
Tableau
Un tableau en JSON est une collection ordonnée de valeurs, qui peuvent être de différents types (nombre, chaîne de caractères, booléen, objet, null). Voici un exemple :
{
"taches": [
{
"id": 1,
"nom": "Faire les courses",
"est_terminee": false
},
{
"id": 2,
"nom": "Nettoyer la maison",
"est_terminee": true
}
]
}
Les objets imbriqués
Vous pouvez également avoir des objets imbriqués dans vos structures JSON. Voici un exemple :
{
"utilisateur": {
"nom": "John",
"age": 30,
"adresse": {
"rue": "123 Main St",
"ville": "Anytown"
}
}
}
Mise en pratique : projet fil rouge
Pour ce mini-projet, nous allons créer un simple gestionnaire de tâches qui permet d'afficher et de modifier des tâches. Nous utiliserons Node.js pour le backend.
Étape 1 : Créer les fichiers
Créez trois fichiers : app.js, tasks.json et .gitignore.
mkdir task-manager
cd task-manager
touch app.js tasks.json .gitignore
Ajoutez le contenu suivant au fichier .gitignore :
node_modules/
npm-debug.log*
Étape 2 : Configurer Express
Installez Express, un framework web pour Node.js.
npm init -y
npm install express
Ajoutez le code suivant à app.js :
// Importer les modules nécessaires
const express = require('express');
const fs = require('fs');
const path = require('path');
// Créer une application Express
const app = express();
const port = 3000;
// Middleware pour parser le corps des requêtes JSON
app.use(express.json());
// Route pour récupérer toutes les tâches
app.get('/tasks', (req, res) => {
const tasksPath = path.join(__dirname, 'tasks.json');
fs.readFile(tasksPath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send('Error reading file.');
}
const tasks = JSON.parse(data);
res.json(tasks);
});
});
// Route pour ajouter une nouvelle tâche
app.post('/tasks', (req, res) => {
const newTask = req.body;
const tasksPath = path.join(__dirname, 'tasks.json');
fs.readFile(tasksPath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send('Error reading file.');
}
let tasks = JSON.parse(data);
tasks.push(newTask);
fs.writeFile(tasksPath, JSON.stringify(tasks, null, 2), (err) => {
if (err) {
return res.status(500).send('Error writing file.');
}
res.status(201).json(newTask);
});
});
});
// Démarrer le serveur
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Étape 3 : Créer les tâches initiales
Ajoutez quelques tâches au fichier tasks.json :
{
"taches": [
{
"id": 1,
"nom": "Faire les courses",
"est_terminee": false
},
{
"id": 2,
"nom": "Nettoyer la maison",
"est_terminee": true
}
]
}
Étape 4 : Tester l'application
Lancez votre application avec la commande suivante :
node app.js
Ouvrez votre navigateur et accédez à http://localhost:3000/tasks. Vous devriez voir les tâches affichées.
Erreurs fréquentes et debugging
Erreur 1 : SyntaxError: Unexpected end of JSON input
Code incorrect :
const data = fs.readFileSync('tasks.json');
const tasks = JSON.parse(data);
Code correct :
fs.readFile('tasks.json', 'utf8', (err, data) => {
if (err) {
return console.error(err);
}
const tasks = JSON.parse(data);
// Traitement des tâches
});
Erreur 2 : TypeError: Cannot read property 'push' of undefined
Code incorrect :
const tasksPath = path.join(__dirname, 'tasks.json');
let tasks = JSON.parse(fs.readFileSync(tasksPath));
tasks.push(newTask);
fs.writeFileSync(tasksPath, JSON.stringify(tasks));
Code correct :
fs.readFile('tasks.json', 'utf8', (err, data) => {
if (err) {
return console.error(err);
}
let tasks = JSON.parse(data) || { taches: [] };
tasks.taches.push(newTask);
fs.writeFile(tasksPath, JSON.stringify(tasks, null, 2), (err) => {
if (err) {
return console.error(err);
}
// Traitement des tâches
});
});
Erreur 3 : Error: ENOENT: no such file or directory
Code incorrect :
const tasks = JSON.parse(fs.readFileSync('tasks.json'));
Code correct :
fs.readFile('tasks.json', 'utf8', (err, data) => {
if (err) {
return console.error(err);
}
const tasks = JSON.parse(data);
// Traitement des tâches
});
Pour aller plus loin
Piste 1 : Ajouter la possibilité de modifier et de supprimer des tâches
Ajoutez des routes pour mettre à jour et supprimer des tâches. Voici un exemple :
app.put('/tasks/:id', (req, res) => {
const taskId = req.params.id;
const updatedTask = req.body;
const tasksPath = path.join(__dirname, 'tasks.json');
fs.readFile(tasksPath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send('Error reading file.');
}
let tasks = JSON.parse(data);
tasks.taches = tasks.taches.map(task =>
task.id == taskId ? { ...task, ...updatedTask } : task
);
fs.writeFile(tasksPath, JSON.stringify(tasks, null, 2), (err) => {
if (err) {
return res.status(500).send('Error writing file.');
}
res.json(updatedTask);
});
});
});
app.delete('/tasks/:id', (req, res) => {
const taskId = req.params.id;
const tasksPath = path.join(__dirname, 'tasks.json');
fs.readFile(tasksPath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send('Error reading file.');
}
let tasks = JSON.parse(data);
tasks.taches = tasks.taches.filter(task => task.id != taskId);
fs.writeFile(tasksPath, JSON.stringify(tasks, null, 2), (err) => {
if (err) {
return res.status(500).send('Error writing file.');
}
res.status(204).send();
});
});
});
Piste 2 : Utiliser une base de données pour stocker les tâches
Vous pouvez utiliser une base de données comme MongoDB ou PostgreSQL pour stocker les tâches. Voici un exemple avec MongoDB :
npm install mongodb
Ajoutez le code suivant à app.js :
const { MongoClient } = require('mongodb');
const uri = "your_mongodb_connection_string";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
async function run() {
try {
await client.connect();
const database = client.db('task-manager');
const collection = database.collection('tasks');
app.get('/tasks', async (req, res) => {
const tasks = await collection.find({}).toArray();
res.json(tasks);
});
app.post('/tasks', async (req, res) => {
const newTask = req.body;
const result = await collection.insertOne(newTask);
res.status(201).json(result.ops[0]);
});
} finally {
await client.close();
}
}
run().catch(console.dir);
Piste 3 : Ajouter une interface utilisateur avec HTML et CSS
Vous pouvez créer une interface utilisateur simple en utilisant HTML et CSS. Voici un exemple :
Créez un fichier index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Manager</title>
<style>
body { font-family: Arial, sans-serif; }
.task { border-bottom: 1px solid #ccc; padding: 10px; }
.add-task { margin-top: 20px; }
</style>
</head>
<body>
<h1>Task Manager</h1>
<div class="add-task">
<input type="text" id="taskName" placeholder="New task name">
<button onclick="addTask()">Add Task</button>
</div>
<script>
async function fetchTasks() {
const response = await fetch('http://localhost:3000/tasks');
const tasks = await response.json();
document.getElementById('tasks').innerHTML = '';
tasks.forEach(task => {
const li = document.createElement('li');
li.className = 'task';
li.innerHTML = `
<span>${task.nom}</span>
<button onclick="deleteTask(${task.id})">Delete</button>
`;
document.getElementById('tasks').appendChild(li);
});
}
async function addTask() {
const taskName = document.getElementById('taskName').value;
await fetch('http://localhost:3000/tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nom: taskName, est_terminee: false })
});
fetchTasks();
}
async function deleteTask(id) {
await fetch(`http://localhost:3000/tasks/${id}`, {
method: 'DELETE'
});
fetchTasks();
}
fetchTasks();
</script>
</body>
</html>
Ajoutez le fichier index.html à votre projet et accédez-y dans votre navigateur pour voir l'interface utilisateur.
Défi pratique
Créez un API de blog simple avec les fonctionnalités suivantes :
- Créer un article
- Lire tous les articles
- Mettre à jour un article
- Supprimer un article
Utilisez Node.js, Express et MongoDB pour le backend.