Lesson 4
Building a Simple API on Mock Data
Intro

In this lesson, you'll learn how to build a simple API using Express.js and mock data. We'll cover setting up an Express.js server, creating mock data, writing endpoints, and retrieving data.

What you'll learn

By the end of this lesson, you will:

  • Set up an Express.js server
  • Create mock data arrays
  • Write POST endpoints for adding data
  • Write GET endpoints for retrieving data
  • Start your server
Step 1: Setting up Express.js

Here we'll learn to set up an Express.js server. This is crucial as it forms the backbone of our API, giving us a robust platform to build on.

JavaScript
1const express = require('express'); // Import Express.js library 2 3const app = express(); // Create an instance of Express 4const PORT = 3000; // Port where the server will listen 5 6app.use(express.json()); // Middleware to parse JSON request bodies

To set up an Express.js server, we first need to import the Express library using require('express'). Then, we create an instance of the Express application by calling express(). We define a port number where the server will be listening for requests; in this case, it’s set to 3000. Additionally, we use a middleware function express.json() which allows our server to parse JSON data in the request bodies. This setup is fundamental as it creates the environment where our API can live and function.

Step 2: Creating Mock Data

Let's move to creating mock data arrays. We do this to simulate a real-world scenario and not use a complex database. This is for learning purposes, and in real-life scenarios, you'll always be using real databases.

JavaScript
1// Mock data 2const users = [ 3 { id: 1, name: 'John Doe', email: 'john@example.com' }, 4 { id: 2, name: 'Jane Doe', email: 'jane@example.com' }, 5 { id: 3, name: 'Sam Smith', email: 'sam@example.com' }, 6]; 7 8const posts = [ 9 { id: 1, title: 'First Post', content: 'This is the first post', userId: 1 }, 10 { id: 2, title: 'Second Post', content: 'This is the second post', userId: 2 }, 11]; 12 13const categories = [ 14 { id: 1, name: 'Tech', posts: [1] }, 15 { id: 2, name: 'Lifestyle', posts: [2] }, 16];

Instead of diving into database management, we create mock data to simulate real data. This step involves defining arrays for users, posts, and categories. These arrays hold objects that represent typical data entities you would encounter in a real-world situation. For users, each object contains an id, name, and email. The posts array includes id, title, content, and userId (to link posts to specific users). Lastly, the categories array comprises id, name, and posts (an array of post IDs under that category). Using mock data keeps things simple and focuses on learning the core concepts.

Step 3: Adding POST Endpoints

We'll now create POST endpoints to add data. This is critical for allowing our API to accept new data entries from users.

Creating a User:

We create a POST endpoint to handle adding new users to our system. This is essential for allowing user registrations and onboarding.

JavaScript
1// Create a User 2app.post('/users', (req, res) => { 3 const { name, email } = req.body; 4 if (!name || !email) { 5 return res.status(400).json({ message: 'Name and email are required' }); 6 } 7 const newUser = { id: users.length + 1, name, email }; 8 users.push(newUser); 9 res.status(201).json(newUser); 10});

To add new users, we define the /users endpoint using app.post(). This endpoint expects a request body containing name and email. We first check if these fields are present using a simple validation. If either name or email is missing, we return a 400 status code with a relevant message. If the data is valid, we create a new user object with a unique id, add it to the users array, and then return the newly created user along with a 201 status code indicating a successful creation.

Creating a Post:

We create a POST endpoint for adding new posts. This is important for allowing users to contribute content to the platform.

JavaScript
1// Create a Post 2app.post('/posts', (req, res) => { 3 const { title, content, userId } = req.body; 4 if (!title || !content || !userId) { 5 return res.status(400).json({ message: 'Title, content, and userId are required' }); 6 } 7 const newPost = { id: posts.length + 1, title, content, userId }; 8 posts.push(newPost); 9 res.status(201).json(newPost); 10});

The process of adding posts is similar to adding users. Here, the /posts endpoint is defined using app.post(). It expects a request body containing title, content, and userId. We validate these fields and if any are missing, a 400 status code is returned. If the data is valid, a new post object is created with a unique id, and the post is added to the posts array. We then return the newly created post along with a 201 status code.

Creating a Category:

We create a POST endpoint for adding new categories. This is helpful for organizing posts into different groups.

JavaScript
1// Create a Category 2app.post('/categories', (req, res) => { 3 const { name, posts } = req.body; 4 if (!name || !Array.isArray(posts)) { 5 return res.status(400).json({ message: 'Name and posts array are required' }); 6 } 7 const newCategory = { id: categories.length + 1, name, posts }; 8 categories.push(newCategory); 9 res.status(201).json(newCategory); 10});

For categories, the endpoint expects name and posts array in the request body. Similar validation is performed to ensure name is provided and posts is an array. If validation fails, a 400 status code is returned. Upon successful validation, a new category object is created and added to the categories array. The newly created category is then returned with a 201 status code.

Step 4: Adding GET Endpoints

Next, we’ll add GET endpoints to retrieve data. GET endpoints are important for fetching and displaying existing data to users.

Retrieve a Single Post with the User:

We create a GET endpoint for retrieving a single post along with the user who created it. This is useful for displaying detailed post information on your frontend.

JavaScript
1// Retrieve a Post with the associated User 2app.get('/posts/:id', (req, res) => { 3 const post = posts.find(p => p.id === parseInt(req.params.id)); // Find post by ID 4 if (!post) res.status(404).send('Post not found'); // Handle not found 5 6 const user = users.find(u => u.id === post.userId); // Find associated user 7 res.json({ ...post, user }); // Return post with user details 8});

To retrieve a single post, we use the /posts/:id endpoint. The :id part of the URL is a route parameter that allows us to capture the specific post ID from the request. We search the posts array for a post matching the provided ID. If no matching post is found, a 404 status code is returned along with a "Post not found" message. If the post is found, we then search for the user associated with the post using the userId. Finally, we return the post along with the user details.

Retrieve All Posts with Users:

We create a GET endpoint to retrieve all posts along with their associated users. This is beneficial for showing a list of posts with author details.

JavaScript
1// Retrieve all Posts 2app.get('/posts', (req, res) => { 3 const detailedPosts = posts.map(post => { 4 const user = users.find(u => u.id === post.userId); // Find user for each post 5 return { ...post, user }; // Combine post with user details 6 }); 7 res.json(detailedPosts); // Return combined data 8});

For retrieving all posts with their corresponding users, the /posts endpoint is defined. We map through each post in the posts array and find the related user using the userId. We then combine the post data with the user data to create a detailed post object. The array of detailed posts is then returned as the response.

Step 5: Starting Your Server

Finally, we start the server to listen for incoming requests. This step puts everything together, making your API live and accessible.

JavaScript
1// Start the server 2app.listen(PORT, () => { 3 console.log(`Server running on http://localhost:${PORT}`); 4});

To start the server, we use the app.listen() method, passing in the port number defined earlier. We also provide a callback function that logs a message indicating the server is running. This is the final step to make your API operational and ready to handle requests.

Conclusion

You've now learned how to set up an Express.js server, create mock data, write endpoints for adding and retrieving data, and start your server. Practice these concepts to reinforce your understanding. Happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.