Skip to content

Instantly share code, notes, and snippets.

@bknie1
Last active April 11, 2020 19:57
Show Gist options
  • Select an option

  • Save bknie1/25fdd4445a609037b23596a78601df23 to your computer and use it in GitHub Desktop.

Select an option

Save bknie1/25fdd4445a609037b23596a78601df23 to your computer and use it in GitHub Desktop.
Creating JSON APIs with Node.js and MongoDB

Creating JSON APIs with Node.js and MongoDB

Reference Project


Table of Contents

Introduction

API Architecture

Responding with JSON

Full Implementation

Conclusion


Introduction

TOC Shortcut

This guide is focused around preparing for a React based stack. React relies heavily on a single-page application (SPA) design pattern, so having a functional API is essential to this, given the additional reliance on asynchronous operations. The guide assumes basic familiarity with HTTP requests, RESTful routing, and Express.js apps.

This guide will help you build a JSON API. Then, you can use this API to build an AJAX SPA (not included).

Single-Page Applications (SPA)

We can mix and match different technologies to accomplish our goal. For the sake of this guide, I will be using React and Express.js to create a SPA with an API. However, there are alternatives:

Front-End

We can use a few different tools on the front end:

  • Vanilla JS
  • jQuery
  • React
  • Angular

Back-End JSON API

We can also use a few different tools on the back end:

  • Express.js
  • Rails
  • Django
  • Flask

API Architecture

TOC Shortcut

In this example we are creating an interactive Todo List. We need to relay the following data:

Field Type
name String
isCompleted Boolean
dateCreated Date

We need to create the following routes:

Verb Route Description
GET /api/todos List all todos
POST /api/todos Create new todo
GET /api/todos/:todoId Retrieve a todo
PUT /api/todos/:todoId Update a todo
DELETE /api/todos/:todoId Delete a todo

Responding with JSON

TOC Shortcut

We can create simple routes that return more than just a page or text:

const express = require("express");
const app = express()

app.get("/", (req, res) => {
	res.send({
    message: "Hello from a JSON!"
  });
});

app.get("*", (req, res) => {
	res.redirect("/");
});

Despite our call to res.send(), Express identifies that we are only passing a JSON, and instead uses res.json(). The developer may use either and it will yield the same result:

res.send({
    message: "Hello from a JSON!"
  });
  // is the same as:
  res.json({
    message: "Hello from a JSON!"
  });

Full Implementation

TOC Shortcut

First, we need to create a schema and model for our Todo items:

const mongoose = require("mongoose");

const todoSchema = new mongoose.Schema({
	name: {
		type: String,
		required: "Item must have a name."
	},
	isComplete: {
		type: Boolean,
		default: false
	},
	dateCreated: {
		type: Date,
		default: Date.now
	}
});

module.exports = mongoose.model("Todo", todoSchema);

Leveraging body-parser, the Todo model we created, and Promises, we can create helper functions that perform all the requests we require. MongoDB gives us JSON objects anyway so, unlike more typical routes, we skip the post-processing step.

Note: Please refer to the reference project linked at the beginning of the guide for the full code. This has been distilled down into the essentials.

var db = require("../models");

exports.getTodos = (req, res) => {
	/// Gets all Todo items
	db.Todo.find().then((data) => {
		console.log(data);
		res.json(data)
	}).catch((err) => {
		res.send(err);
	});
}

exports.createTodo = (req, res) => {
	db.Todo.create(req.body).then((data) => {
		console.log(data);
		res.json(data);
	})
	.catch( (err) => {
		res.send(err);
	});
}

exports.getTodo = (req, res) => {
	/// Gets a specific Todo
	db.Todo.findById({_id: req.params.id}).then((data) => {
		console.log(data);
		res.json(data);
	}).catch((err) => {
		res.send(err);
	});
}

exports.updateTodo = (req, res) => {
	// Note: The request body contains our update info.
	db.Todo.findOneAndUpdate({_id: req.params.id}, req.body).then((data) => {
		res.json(data);
	}).catch((err) => {
		res.send(err);
	});
}

exports.deleteTodo = (req, res) => {
	db.Todo.findByIdAndRemove({_id: req.params.id}).then((data) => {
		console.log(`Deleted ${data}`);
		res.json(data);
	})
	.catch((err) => {
		res.send(err);
	});
}

These are, in turn, used by our routes:

const express = require("express");
const router = express.Router();
const db = require("../models");
const todoHelper = require("../helpers/todos");

// /api/todos
router.route("/")
	.get(todoHelper.getTodos)
	.post(todoHelper.createTodo)

// /api/todos/:id
router.route("/:id")
	.get(todoHelper.getTodo)
	.put(todoHelper.updateTodo)
	.delete(todoHelper.deleteTodo)

module.exports = router;

Conclusion

TOC Shortcut

It is now up to the developer to interact with our API and determine the best way to present information for their own site. APIs offer unparalleled flexibility; we are no longer bound to serving information on a particular page in a specific way. APIs may even serve similar information to similar users, but each user may have their own customized experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment