NodeJS #19: Menyimpan Data ke File JSON – Database Sederhana

🍭 NodeJS #19: Menyimpan Data ke File JSON – Database Sederhana

Halo, calon backend developer! 👋

Selama ini kita menyimpan data di dalam memori (array atau objek di dalam kode). Setiap kali server mati, data hilang. Agar data bisa tersimpan permanen, kita perlu menyimpannya ke dalam file. Di tutorial ini, kita akan belajar menggunakan modul fs (file system) milik Node.js untuk membaca dan menulis file JSON. Dengan ini, kita bisa membuat database sederhana berbasis file. Cocok untuk proyek kecil atau belajar sebelum menggunakan database sungguhan seperti MySQL atau MongoDB. Yuk, kita mulai! 🚀

📦 Apa itu Modul fs?

fs adalah modul bawaan Node.js yang memungkinkan kita berinteraksi dengan file sistem. Kita bisa membaca file, menulis file, menghapus file, dan lain-lain. Untuk menyimpan data, kita akan gunakan format JSON karena mudah dibaca dan ditulis, serta strukturnya mirip dengan objek JavaScript.

Bayangkan file JSON seperti lemari arsip. Kita bisa menyimpan banyak data di dalamnya, dan setiap kali aplikasi butuh data, kita buka lemari itu (baca file). Setelah ada perubahan, kita simpan lagi (tulis file).

📁 Persiapan Proyek

Buat folder baru, misal simpan-json. Inisialisasi npm dan instal express (kita akan buat API sederhana).

npm init -y
npm install express

Buat file app.js dan folder data (untuk menyimpan file JSON).

🗂️ Membuat File JSON Awal

Kita akan gunakan file data/buah.json untuk menyimpan daftar buah. Buat file tersebut dengan isi awal array kosong [] atau dengan data contoh.

// data/buah.json
[
  { "id": 1, "nama": "Apel", "warna": "Merah", "harga": 5000 },
  { "id": 2, "nama": "Jeruk", "warna": "Oranye", "harga": 7000 }
]

📖 Membaca File JSON (READ)

Kita akan buat fungsi untuk membaca file buah.json. Gunakan fs.readFile (asynchronous) atau fs.readFileSync (synchronous). Untuk server, lebih baik gunakan asynchronous agar tidak memblokir proses. Tapi untuk sederhana, kita pakai sync dulu.

Di app.js, tulis:

const express = require('express');
const fs = require('fs'); // import modul fs
const path = require('path'); // untuk mengurus path file
const app = express();
const port = 3000;

// Middleware untuk membaca JSON dari request body
app.use(express.json());

// Path ke file data
const dataFile = path.join(__dirname, 'data', 'buah.json');

// Fungsi baca data
function bacaData() {
  const data = fs.readFileSync(dataFile, 'utf8');
  return JSON.parse(data); // ubah string JSON menjadi array/objek
}

// GET semua buah
app.get('/api/buah', (req, res) => {
  const buah = bacaData();
  res.json(buah);
});

// GET satu buah by id
app.get('/api/buah/:id', (req, res) => {
  const buah = bacaData();
  const id = parseInt(req.params.id);
  const item = buah.find(b => b.id === id);
  if (item) {
    res.json(item);
  } else {
    res.status(404).json({ pesan: 'Buah tidak ditemukan' });
  }
});

app.listen(port, () => {
  console.log(`Server berjalan di http://localhost:${port}`);
});

Jalankan dengan node app.js dan akses /api/buah. Data dari file akan tampil.

💡 fs.readFileSync membaca file secara sinkron, artinya kode berikutnya akan menunggu sampai pembacaan selesai. Untuk server dengan banyak request, sebaiknya gunakan versi async fs.readFile dengan callback atau Promise.

✍️ Menulis File JSON (WRITE)

Sekarang kita buat fungsi untuk menulis data ke file. Kita akan tambahkan endpoint POST untuk menambah buah baru.

// Fungsi tulis data
function tulisData(data) {
  fs.writeFileSync(dataFile, JSON.stringify(data, null, 2));
}

// POST tambah buah
app.post('/api/buah', (req, res) => {
  const buah = bacaData();
  const buahBaru = {
    id: buah.length > 0 ? buah[buah.length - 1].id + 1 : 1,
    nama: req.body.nama,
    warna: req.body.warna,
    harga: req.body.harga
  };

  // Validasi sederhana
  if (!buahBaru.nama || !buahBaru.warna || !buahBaru.harga) {
    return res.status(400).json({ pesan: 'Data tidak lengkap' });
  }

  buah.push(buahBaru);
  tulisData(buah);
  res.status(201).json(buahBaru);
});

Penjelasan:

  • JSON.stringify(data, null, 2) mengubah objek menjadi string JSON dengan indentasi 2 spasi agar rapi.
  • ID baru dihitung dari ID terakhir + 1, atau 1 jika array kosong.
  • Setelah menambah, kita panggil tulisData untuk menyimpan perubahan.

Coba dengan Postman: method POST ke http://localhost:3000/api/buah dengan body JSON:

{
  "nama": "Mangga",
  "warna": "Kuning",
  "harga": 10000
}

Setelah itu, GET lagi untuk melihat data baru. Buka file buah.json, pasti sudah berubah.

🔄 Update Data (PUT)

Kita tambahkan endpoint untuk mengupdate buah berdasarkan ID.

// PUT update buah
app.put('/api/buah/:id', (req, res) => {
  const buah = bacaData();
  const id = parseInt(req.params.id);
  const index = buah.findIndex(b => b.id === id);

  if (index === -1) {
    return res.status(404).json({ pesan: 'Buah tidak ditemukan' });
  }

  // Update data (hanya field yang dikirim)
  const { nama, warna, harga } = req.body;
  if (nama) buah[index].nama = nama;
  if (warna) buah[index].warna = warna;
  if (harga) buah[index].harga = harga;

  tulisData(buah);
  res.json(buah[index]);
});

❌ Delete Data (DELETE)

// DELETE hapus buah
app.delete('/api/buah/:id', (req, res) => {
  let buah = bacaData();
  const id = parseInt(req.params.id);
  const newBuah = buah.filter(b => b.id !== id);

  if (newBuah.length === buah.length) {
    return res.status(404).json({ pesan: 'Buah tidak ditemukan' });
  }

  tulisData(newBuah);
  res.json({ pesan: 'Buah berhasil dihapus' });
});
⚠️ Penting: Operasi baca/tulis file tidak cocok untuk aplikasi dengan banyak pengguna karena bisa terjadi race condition (dua request mencoba menulis bersamaan). Untuk skala kecil atau belajar, ini cukup. Untuk produksi, gunakan database sungguhan.

📂 Menggunakan Async Version (Lebih Baik untuk Server)

Untuk menghindari blocking, kita bisa gunakan versi async. Contoh:

// Fungsi baca async
function bacaDataAsync(callback) {
  fs.readFile(dataFile, 'utf8', (err, data) => {
    if (err) {
      callback(err, null);
    } else {
      callback(null, JSON.parse(data));
    }
  });
}

// Atau gunakan Promise
const { promises: fsPromises } = require('fs');

async function bacaDataPromise() {
  const data = await fsPromises.readFile(dataFile, 'utf8');
  return JSON.parse(data);
}

Kita bisa gunakan fsPromises yang lebih modern dengan async/await. Silakan pelajari sendiri sebagai latihan.

🧪 Latihan Mandiri

  1. Buat file data/siswa.json dan buat API CRUD untuk data siswa (id, nama, kelas, nilai).
  2. Tambahkan validasi: saat POST, pastikan semua field ada. Saat PUT, pastikan ID ada.
  3. Buat endpoint GET untuk mencari siswa berdasarkan nama (gunakan query parameter).
  4. Gunakan fsPromises (async/await) untuk semua operasi file.

📚 Rangkuman

Operasi Fungsi Sync Fungsi Async (Promise)
Baca file fs.readFileSync(path, 'utf8') fsPromises.readFile(path, 'utf8')
Tulis file fs.writeFileSync(path, data) fsPromises.writeFile(path, data)
Ubah JSON JSON.parse() dan JSON.stringify() sama

🏁 Penutup

Sekarang kamu sudah bisa menyimpan data secara permanen ke file JSON. Ini adalah langkah awal sebelum menggunakan database sesungguhnya. Di tutorial selanjutnya (NodeJS #20) kita akan belajar membuat API POST untuk menambah data lebih dalam, serta menangani berbagai kemungkinan error. Sampai jumpa!

Jangan lupa untuk mencoba latihan dan bereksperimen sendiri. Kalau ada pertanyaan, tulis di komentar. Selamat coding! 💻😊


Ditulis dengan ❤️ untuk para pemula yang ingin menjadi programmer handal.

Lebih baru Lebih lama

نموذج الاتصال