Learn how to create, read, update, and delete student records using Node.js, Express.js, HTTP methods, and JSON data.
CRUD represents the four basic operations used to manage data in an application.
| Operation | Meaning | HTTP Method |
|---|---|---|
| Create | Add a new student | POST |
| Read | View student records | GET |
| Update | Modify student information | PUT or PATCH |
| Delete | Remove a student | DELETE |
Open your terminal and run these commands:
mkdir student-crud-api
cd student-crud-api
npm init -y
npm install express
Create a file named app.js.
Your project structure will be:
student-crud-api/
│
├── node_modules/
├── app.js
├── package.json
└── package-lock.json
First, import Express, create the application, and configure JSON request-body parsing.
const express = require('express');
const app = express();
app.use(express.json());
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
Run the application:
node app.js
The server is now ready to receive requests on port 3000.
For this beginner project, we will store student records in a JavaScript array. Each student will have an ID, name, and course.
const students = [
{ id: 1, name: 'Amit', course: 'Node.js' },
{ id: 2, name: 'Rahul', course: 'JavaScript' },
{ id: 3, name: 'Priya', course: 'React' }
];
The GET method retrieves student records from the API.
app.get('/api/students', (req, res) => {
res.json(students);
});
Test URL:
GET http://localhost:3000/api/students
Example response:
[
{
"id": 1,
"name": "Amit",
"course": "Node.js"
},
{
"id": 2,
"name": "Rahul",
"course": "JavaScript"
},
{
"id": 3,
"name": "Priya",
"course": "React"
}
]
Use a route parameter to find one student by their ID.
app.get('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
const student = students.find(s => s.id === id);
if (!student) {
return res.status(404).json({
message: 'Student not found'
});
}
res.json(student);
});
Test URL:
GET http://localhost:3000/api/students/2
Response:
{
"id": 2,
"name": "Rahul",
"course": "JavaScript"
}
The POST method creates a new student record. The client sends the name and course in the JSON request body.
app.post('/api/students', (req, res) => {
const { name, course } = req.body;
if (
typeof name !== 'string' ||
!name.trim() ||
typeof course !== 'string' ||
!course.trim()
) {
return res.status(400).json({
message: 'Name and course are required'
});
}
const newStudent = {
id: students.length
? Math.max(...students.map(s => s.id)) + 1
: 1,
name: name.trim(),
course: course.trim()
};
students.push(newStudent);
res.status(201).json({
message: 'Student created successfully',
student: newStudent
});
});
Request URL:
POST http://localhost:3000/api/students
Request body (JSON):
{
"name": "Neha",
"course": "Python"
}
Example response:
{
"message": "Student created successfully",
"student": {
"id": 4,
"name": "Neha",
"course": "Python"
}
}
The API returns HTTP status code 201 when the student is created successfully.
The PUT method replaces the editable information of an existing student. In this example, both the name and course are required.
app.put('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
const { name, course } = req.body;
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
if (
typeof name !== 'string' ||
!name.trim() ||
typeof course !== 'string' ||
!course.trim()
) {
return res.status(400).json({
message: 'Name and course are required'
});
}
const student = students.find(s => s.id === id);
if (!student) {
return res.status(404).json({
message: 'Student not found'
});
}
student.name = name.trim();
student.course = course.trim();
res.json({
message: 'Student updated successfully',
student: student
});
});
Request URL:
PUT http://localhost:3000/api/students/2
Request body:
{
"name": "Rahul Kumar",
"course": "React Native"
}
PATCH updates only the fields included in the request body.
app.patch('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
const student = students.find(s => s.id === id);
if (!student) {
return res.status(404).json({
message: 'Student not found'
});
}
const { name, course } = req.body;
if (name === undefined && course === undefined) {
return res.status(400).json({
message: 'Provide at least one field to update'
});
}
if (name !== undefined) {
if (typeof name !== 'string' || !name.trim()) {
return res.status(400).json({
message: 'Name must be a non-empty string'
});
}
student.name = name.trim();
}
if (course !== undefined) {
if (typeof course !== 'string' || !course.trim()) {
return res.status(400).json({
message: 'Course must be a non-empty string'
});
}
student.course = course.trim();
}
res.json({
message: 'Student updated successfully',
student: student
});
});
Example request:
PATCH http://localhost:3000/api/students/2
{
"course": "Node.js Advanced"
}
Only the course changes. The student's name remains unchanged.
The DELETE method removes a student record from the array.
app.delete('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
const index = students.findIndex(s => s.id === id);
if (index === -1) {
return res.status(404).json({
message: 'Student not found'
});
}
students.splice(index, 1);
res.json({
message: 'Student deleted successfully'
});
});
Request URL:
DELETE http://localhost:3000/api/students/3
Example response:
{
"message": "Student deleted successfully"
}
The following is the complete working application. Copy this
code into app.js instead of combining the separate
examples manually.
const express = require('express');
const app = express();
const PORT = 3000;
app.use(express.json());
let students = [
{ id: 1, name: 'Amit', course: 'Node.js' },
{ id: 2, name: 'Rahul', course: 'JavaScript' },
{ id: 3, name: 'Priya', course: 'React' }
];
let nextId = 4;
// GET: Get all students
app.get('/api/students', (req, res) => {
res.json(students);
});
// GET: Get a student by ID
app.get('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
const student = students.find(s => s.id === id);
if (!student) {
return res.status(404).json({
message: 'Student not found'
});
}
res.json(student);
});
// POST: Create a student
app.post('/api/students', (req, res) => {
const { name, course } = req.body;
if (
typeof name !== 'string' ||
!name.trim() ||
typeof course !== 'string' ||
!course.trim()
) {
return res.status(400).json({
message: 'Name and course are required'
});
}
const newStudent = {
id: nextId++,
name: name.trim(),
course: course.trim()
};
students.push(newStudent);
res.status(201).json({
message: 'Student created successfully',
student: newStudent
});
});
// PUT: Replace student details
app.put('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
const { name, course } = req.body;
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
if (
typeof name !== 'string' ||
!name.trim() ||
typeof course !== 'string' ||
!course.trim()
) {
return res.status(400).json({
message: 'Name and course are required'
});
}
const student = students.find(s => s.id === id);
if (!student) {
return res.status(404).json({
message: 'Student not found'
});
}
student.name = name.trim();
student.course = course.trim();
res.json({
message: 'Student updated successfully',
student: student
});
});
// PATCH: Update selected student fields
app.patch('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
const student = students.find(s => s.id === id);
if (!student) {
return res.status(404).json({
message: 'Student not found'
});
}
const { name, course } = req.body;
if (name === undefined && course === undefined) {
return res.status(400).json({
message: 'Provide at least one field to update'
});
}
if (name !== undefined) {
if (typeof name !== 'string' || !name.trim()) {
return res.status(400).json({
message: 'Name must be a non-empty string'
});
}
student.name = name.trim();
}
if (course !== undefined) {
if (typeof course !== 'string' || !course.trim()) {
return res.status(400).json({
message: 'Course must be a non-empty string'
});
}
student.course = course.trim();
}
res.json({
message: 'Student updated successfully',
student: student
});
});
// DELETE: Delete a student
app.delete('/api/students/:id', (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id <= 0) {
return res.status(400).json({
message: 'Invalid student ID'
});
}
const index = students.findIndex(s => s.id === id);
if (index === -1) {
return res.status(404).json({
message: 'Student not found'
});
}
students.splice(index, 1);
res.json({
message: 'Student deleted successfully'
});
});
// Handle unknown routes
app.use((req, res) => {
res.status(404).json({
message: 'API endpoint not found'
});
});
// Handle malformed JSON request bodies
app.use((err, req, res, next) => {
if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
return res.status(400).json({
message: 'Invalid JSON request body'
});
}
console.error(err);
res.status(500).json({
message: 'Internal server error'
});
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
Start your server:
node app.js
| Operation | Method | URL |
|---|---|---|
| Get all students | GET | /api/students |
| Get student ID 1 | GET | /api/students/1 |
| Create student | POST | /api/students |
| Replace student | PUT | /api/students/1 |
| Update selected fields | PATCH | /api/students/1 |
| Delete student | DELETE | /api/students/1 |
For POST, PUT, and PATCH requests:
Build an API for managing employees.
Select the correct answer for each question.