JSON Server
Your Front-end team has been stuck for the Back-end team to finish the API services, to integrate??
OR
You are aware of the JSON pattern received from a 3rd party paid API service call. But during implementation into your business logic it is getting costlier since, each execution of the 3rd party API call, charges some amount??
No worries! Here is the solution!
*********************************************************************
So far we have been habituated of dividing the requirements into smaller modules, after a detailed client requirement analysis.
Briefing the front-end tasks to ‘Front-end Team’ and back-end tasks to ‘Back-end Team’; we define the API URL list and provide them to both the team, along with the JSON samples (of the corresponding API calls return) to get start.
Now the Front-end team may convert the static html (provided by the html design team), to Angular/React/Vue/etc compatible, But in order to make the pages fully dynamic by implementing the needed REST call URLs, ‘Front-end Team’ need to wait for the ‘Back-end Team’ to finish corresponding API services. Hence they might get stuck, which may hamper the production time!
Second issue, we might have faced as,
Let’s say we integrate a 3rd party paid API in our application. For each execution, it charges some cents. For a business logic to integrate, let’s say you need to execute it time & again. In such cases, save the request/response in a josn file and use json-server for dummy REST calls, till the business logic integration correctly. Once it gets fixed, you can use the live url.
By using JSON Server we can solve such obstacle in the development workflow!
What is JSON Server?
How to use it?
- After installing NodeJs, install the package ‘json-server’ by executing:
npm install -g json-server
- Like ‘nodemon’, we install this nmp package globally in our local machine, since this package is helpful for every REST based application. And every time we don’t need to install these common packages separately for each application
- Here we didn’t use ‘--save’, since the package doesn’t need to get uploaded to Production env.
- Or we can install it in development mode for application specific use too:
npm install json-server --dev
A simple Example:
STEP 1: Create a sample.json file.
Let’s say it contains the below data
{
"authors": [
{ "id": 1, "name": "Suresh" },
{ "id": 2, "name": "Ramesh" }
],
"articles": [
{ "id": 1, "title": "What is Goal Setting?", "authorId": 1 },
{ "id": 2, "title": "How to Achieve Your Goals?", "authorID": 1 },
{ "id": 3, "title": "Boost your strength", "authorID": 2 }
],
"comments": [
{ "id": 1, "body": "Lorem Ipsum", "postId": 1 }
]
}
STEP 2: Execute the command:
json-server --watch sample.json
STEP 3: Check in the browser
http://localhost:3000
http://localhost:3000/authors
http://localhost:3000/articles/2
Or
Check all the REST methods through the tools such as ‘Postman’ / TestRESTfulWebServer’
NOTE: The default port for json-server is 3000. However we can change as per our requirement by using - -port while starting the server. Ex:
json-server --watch sample.json --port 3001
Example of implementing json-server call setting inside package.json:
STEP 1: Create the sample.json
STEP 2: Set the script to start the json server inside your package.json.
Recommended by LinkedIn
"scripts": {
.
.
.
"json:server": "json-server --watch sample.json --port 3003"
},
[Note: Here the json server starts @ 3003 port, instaed of the default port 3000]
STEP 3: Execute
npm run --watch json:server
STEP 4: Check the URL
http://localhost:3003/articles etc...
either in browser or check all the REST calls through the tools such as Postman or TestRESTfulWebServer etc.
How to Implement in our real application?
A. Implement in Angular Application:
STEP 1: Create sample.json
STEP 2: Set the hostUrl of the Mock Server inside your real application
src/environments/environment.ts
export const environment = {
production: false,
hostUrl: 'http://localhost:3003'
};
And get start to implement it in all the REST based API service calls!
src/app.module.ts
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';
export class AppComponent {
readonly apiBaseUrl = environment.hostUrl;
msg: string;
authorList = [];
constructor( private http: HttpClient) {
this.getArticleList();
}
getAuthorList(){
this.http.get(this.apiBaseUrl+'/authors').subscribe(
res => {
this.authorList = res;
},
err => {
this.authorMsg = err.error.message;
}
);
}
submitAuthor(formData: NgForm) {
if(formData.value.id !== 0) {
this.http.put(
this.apiBaseUrl+'/authors/' + formData.value.id, formData.value
).subscribe((res: any) => {
window.location.reload();
});
} else {
this.http.post(
this.apiBaseUrl+'/authors', formData.value
).subscribe((res: any) => {
this.getAuthorList();
window.location.reload();
});
}
}
deleteAuthor(id) {
this.http.delete(this.apiBaseUrl+'/authors/' + id).subscribe(
res => {
this.authorMsg = " Record deleted successfully!";
this.getAuthorList();
},
err => {
this.authorMsg = "Record deletion failed!";
}
);
}
editAuthor(id){
this.http.get(this.apiBaseUrl+'/authors/' + id).subscribe(
res => {
this.id = res['id'];
this.name = res['name'];
},
err => {
this.authorMsg = err.error.message;
}
);
}
}
src/app.component.html
<h6>Create Author</h6>
<form #authorForm="ngForm" (ngSubmit)="createAuthor(authorForm)">
<input type="text" name="name" [(ngModel)]="name" placeholder="Name" />
<input type="hidden" name="id" [(ngModel)]="id" />
<button type="submit">Submit</button>
</form><hr />
<h6>Create Author</h6>
{{ authorMsg }}
<ul *ngFor="let data of authorList">
<li>
<label>{{ data.name }}</label>
<a href ="javascript:void(0);" (click)="editAuthor(data.id)">Edit</a> ||
<a href ="javascript:void(0);" (click)="deleteAuthor(data.id)">Delete</a>
</li>
</ul>
B. Implement in React Application:
STEP 1: Create sample.json
STEP 2: Create your component(here Author.jsx), to integrate the API calls.
There are many ways to set those ajax call. Here I have shown 2 such ways.
i. Using fetch() for REST call
src/Author.js
import React from 'react';
class Author extends React.Component {
apiUrl = 'http://localhost:3003';
constructor() {
super();
this.state = {
id: '',
name: '',
msg: '',
authors: []
};
}
componentDidMount(){
this.getAuthors();
}
inputChangeHandler = e =>{
this.setState({
[e.target.name]: e.target.value
});
}
async getAuthors() {
this.setState({ authors: await this.fetch('get', '/authors') });
}
async fetch(method, endpoint, body) {
var API = this.apiUrl;
try {
const res = await fetch(`${API}${endpoint}`, {
method,
body: body && JSON.stringify(body),
headers: {
'content-type': 'application/json',
accept: 'application/json'
},
});
return await res.json();
} catch (error) {
this.setState({ error });
}
}
handleSubmit = async (e) => {
if(!this.state.id) {
let post = {name: this.state.name};
await this.fetch('post', '/authors', post);
} else {
let post = {id: this.state.id, name: this.state.name};
await this.fetch('put', `/authors/${this.state.id}`, post);
}
e.preventDefault();
}
editAuthor = async (id) => {
var author = await this.fetch('get', `/authors/${id}`);
this.setState({ name: author.name, id: author.id });
}
async deleteAuthor(data) {
if (window.confirm(`Are you sure you want to delete "${data.name}"`)) {
await this.fetch('delete', `/authors/${data.id}`);
this.getAuthors();
}
}
render (){
return (
<div>
<h6>Create Author</h6>
<form onSubmit ={this.handleSubmit}>
<input type='text' name='name' value={this.state.name} onChange ={this.inputChangeHandler} />
<input type='hidden' name='id' value={this.state.id} onChange ={this.inputChangeHandler} />
<button type="submit">Submit</button>
</form><hr />
<h6>Author List</h6>
{ this.state.msg }
<ul>
{this.state.authors.map(data =>
<li key={data.id}>
<label>{ data.name }</label>
<button onClick = { () => {this.editAuthor(data.id)} }>Edit</button> ||
<button onClick = { () => {this.deleteAuthor(data)} }>Delete</button>
</li>)}
</ul>
</div>
);
}
}
export default Author;
ii. Using ‘Axios’ for REST calls
src/Author.jsx
import React from 'react';
import axios from 'axios';
const apiUrl = 'http://localhost:3003';
class Author extends React.Component {
constructor() {
super();
this.state = {
id: '',
name: '',
msg: '',
authors: []
};
}
componentDidMount(){
this.getAuthors();
}
getAuthors() {
axios.get(apiUrl + '/authors').then((res) => {
this.setState({ authors: res.data});
});
}
inputChangeHandler = e =>{
this.setState({
[e.target.name]: e.target.value
});
}
handleSubmit = async (e) => {
if(!this.state.id) {
let post = {name: this.state.name};
axios.post(apiUrl + '/authors', post).then((res) => {
this.getAuthors();
});
} else {
let post = {id: this.state.id, name: this.state.name};
axios.put(apiUrl + '/authors/' + this.state.id, post).then((res) => {
this.getAuthors();
});
}
e.preventDefault();
}
editAuthor = async (id) => {
axios.get(apiUrl + '/authors/' + id).then((res) => {
this.setState({ name: res.data.name, id: res.data.id });
});
}
deleteAuthor(data) {
if (window.confirm(`Are you sure you want to delete "${data.name}"`)) {
axios.delete(apiUrl + '/authors/' + data.id).then((res) => {
this.getAuthors();
});
}
}
render (){
return (
<div>
<h6>Create Author</h6>
<form onSubmit ={this.handleSubmit}>
<input type='text' name='name' value={this.state.name} onChange = {this.inputChangeHandler} />
<input type='hidden' name='id' value={this.state.id} onChange = {this.inputChangeHandler} />
<button type="submit">Submit</button>
</form><hr />
<h6>Author List</h6>
{ this.state.msg }
<ul>
{this.state.authors.map(data =>
<li key={data.id}>
<label>{ data.name }</label>
<button onClick = { () => {this.editAuthor(data.id)} }>Edit</button> ||
<button onClick = { () => {this.deleteAuthor(data)} }>Delete</button>
</li>)}
</ul>
</div>
);
}
}
export default Author;
STEP 3: Include Author component in app.js
src/app.js
import Author from './Author';
function App() {
return (
<div>
<Author />
</div>
);
}
export default App;
STEP 4: Check all the CRUD operation to test the REST calls.
Summary:
->In this way, we use sample json in JSON Server.
->We get the JSON Server started on port 3003, which provides all the testing urls for API Service calls.
->We set that hostUrl in our real application(Angular / React) and implemented our business logic for the CRUD operation.
Hence Front-end team doesn't need to wait for the Back-end team to finish their tasks, in order to integrate the API call url, once after getting the sample request/response json. They can create such mock server in their local development space and integrate all the calls and finish their task. Once the Back-end team finishes their task, they can overwrite the hostUrl path only!
Again for the 3rd party paid API stuff, once the team has the sample json received from the 3rd Party API, they can save in their local json file. Start json server to get dummy URL, Integrate in the controller, And Doing after all the R&D and business logic integration they can replace the dummy url with the actual live url.
IT Project Manager
4yReally helpful article Ipsita.