🗄️ Mini-Projet — API Articles avec Persistance JSON
API REST avec persistance sur disque via la classe JsonDB — les données survivent aux redémarrages du serveur.
Aperçu
Ce mini-projet démontre la persistance des données sans base de données externe.
La classe JsonDB lit et écrit dans db.json à chaque opération CRUD.
Au démarrage, si la base est vide, 3 articles de seed sont insérés automatiquement.
JSON
Persistance fichier
3009
Port
0
Dépendances externes
Classe JsonDB — Explication
La classe JsonDB encapsule toutes les opérations fichier.
Elle est instanciée une seule fois au démarrage et partagée par toutes les routes.
constructor(filename)— charge le fichier en mémoire dansthis.data_load()— lit + parse le JSON, retourne{"{ articles: [] }"}en cas d'erreur_save()— sérialisethis.dataet l'écrit sur le disquefindAll()— retourne le tableauarticlesfindById(id)— cherche avec.find()etparseInt(id)insert(article)— auto-increment ID +createdAt+ push + saveupdate(id, data)— merge spread + savedelete(id)— filter + save, retourne bool
class JsonDB {
constructor(filename) {
this.filepath = path.join(__dirname, filename);
this.data = this._load();
}
_load() {
try { return JSON.parse(fs.readFileSync(this.filepath, 'utf-8')); }
catch { return { articles: [] }; }
}
_save() { fs.writeFileSync(this.filepath, JSON.stringify(this.data, null, 2)); }
findAll() { return this.data.articles; }
findById(id){ return this.data.articles.find(a => a.id === parseInt(id)); }
insert(article) {
const ids = this.data.articles.map(a => a.id);
article.id = ids.length ? Math.max(...ids) + 1 : 1;
article.createdAt = new Date().toISOString();
this.data.articles.push(article);
this._save();
return article;
}
// update() et delete() similaires...
}
server.js — Routes Express
const db = new JsonDB('db.json');
// Seed automatique si vide
if (db.findAll().length === 0) {
['Node.js et les streams', 'Express middleware', 'JWT auth'].forEach((titre, i) => {
db.insert({ titre, auteur: 'Formateur', contenu: 'Contenu ' + (i+1), tags: ['nodejs'] });
});
}
app.get('/articles', (req, res) => res.json({ success: true, data: db.findAll() }));
app.get('/articles/:id', (req, res) => {
const a = db.findById(req.params.id);
if (!a) return res.status(404).json({ success: false, error: 'Article introuvable' });
res.json({ success: true, data: a });
});
app.post('/articles', (req, res) => {
const { titre, auteur } = req.body;
if (!titre || !auteur) return res.status(400).json({ success: false, error: 'titre et auteur requis' });
res.status(201).json({ success: true, data: db.insert(req.body) });
});
app.put('/articles/:id', (req, res) => {
const a = db.update(req.params.id, req.body);
if (!a) return res.status(404).json({ success: false, error: 'Article introuvable' });
res.json({ success: true, data: a });
});
app.delete('/articles/:id', (req, res) => {
if (!db.delete(req.params.id)) return res.status(404).json({ success: false, error: 'Article introuvable' });
res.status(204).send();
});
Endpoints
Exemples curl
# Démarrer
npm install && node server.js
# Lister les articles (seed automatique)
curl http://localhost:3009/articles
# Créer un article
curl -X POST http://localhost:3009/articles \
-H "Content-Type: application/json" \
-d '{"titre":"Mon article","auteur":"Alice","contenu":"Contenu ici"}'
# Modifier
curl -X PUT http://localhost:3009/articles/1 \
-H "Content-Type: application/json" \
-d '{"titre":"Titre modifié","auteur":"Alice","contenu":"Nouveau contenu"}'
# Supprimer
curl -X DELETE http://localhost:3009/articles/2
# → 204 No Content (fichier db.json mis à jour)