/ AngularJS

Prototyping Angular UIs without a real backend

When creating a prototype or demonstration of a new app idea, you don't want to get bogged down in the backend. All your focus needs to be on the user interface, so how can you mock out the backend yet still make the app as functional as possible?

When working with Angular, you're typically dealing with a REST API. Hardcoding data or faking responses can make your app feel rigid and limited.

So what you want is a real API, a dynamic API, just without the fuss of making one from scratch.

This is where JSON Server can help you.

JSON Server

JSON Server is an awesome little npm package, which like it's tagline clearly states, makes it extremely easy to create a JSON API:

Get a full fake REST API with zero coding in less than 30 seconds (seriously)
— JSON Server

At it's simplest, JSON Server needs a single JSON "database" file - arrays of customers, orders, widget, whatever you need.

Using this "database", JSON Server fires up an API which provides endpoints to GET, PUT, POST, PATCH, and DELETE items.

It all works based on a single JSON file!

That's what makes it so simple to get started with.

Your JSON file will serve multiple purposes:

  • it defines the API resources you will have,
  • including any seed data to those resources,
  • and is the file where changes (PUT, POST, DELETE) will be persisted.

This last point is what makes it great for demonstrations.

You can pre-cook some data ready for your demo. Any changes you make will be saved to the file as you go, giving your app the responsiveness and flow you need.

When you're ready to reset the data and start again, simply revert back to the original JSON file. Simple.

Getting the basics going

The very first time you want to use JSON Server, you'll need to install as globally by using:

$ npm install -g json-server

Once installed, you're ready to create your API.

So if your JSON file (let's call it db.json) has the following:

{
    "customers":[
        {
            "id": 1,
            "name": "Sample Customer",
            "address": "1 The Street"
        }
    ],
    "orders":[],
    "discounts":[]
}

When you start JSON Server on the command line using $ json-server db.json, you'll have the following endpoints:

http://localhost:3000/customers
http://localhost:3000/orders
http://localhost:3000/discounts

If you did a GET to http://localhost:3000/customers/1, you'd get back:

{
    "id": 1,
    "name": "Sample Customer",
    "address": "1 The Street"
}

A Brief Example

There's no point going through everything that JSON Server can do, that is all for you on the GitHub page.

However, it's worth highlighting how relationships between resources work, and how you can use query string parameters like _embed and _expand to craft the API responses into something usable.

Let's say that you want to see a customer along with their orders and discounts.

Relationships between resources are denoted by identity properties following the convention of {{resourceName}}Id.

So if you had an order that had a customerId property, JSON Server will assume a relationship.

You could make multiple API calls, one to /customers and then one to /orders to get all their orders.

It would be easier if you could combine those into a single call instead.

Embedding related resources

If you made a request to GET /customers/1?_embed=orders, you'd be asking JSON Server to include all related orders (child resources) at the same time as the customer (parent resource) data.

You'd get back something like this:

{
    "id": 1,
    "name": "Sample Customer",
    "address": "1 The Street",
    "orders": [
        {
            "id": 1,
            "product":"Apples",
            "quantity": 5        
        },
        {
            "id": 2,
            "product":"Oranges",
            "quantity": 2
        }
    ]
}

When you want to include related discounts too, you could make a request to GET /customers/?_embed=orders&_embed=discounts.

That would give you back something like this:

{
    "id": 1,
    "name": "Sample Customer",
    "address": "1 The Street",
    "orders": [
        {
            "id": 1,
            "product":"Apples",
            "quantity": 5        
        },
        {
            "id": 2,
            "product":"Oranges",
            "quantity": 2
        }
    ],
    "discounts": [
        {
            "id": 1,
            "name": "Regular Customer - 10% off"
        }
    ]
}

Note that the _embed value isn't a comma separated list. So ?_embed=orders,discounts won't work, instead you need two _embed parameters: ?_embed=orders&_embed=discounts

How about the inverse of that?

You can use _expand to do the inverse of this to include the parent resource in child resource.

Say you want to get an order (child resource), along with the related customer (parent resource).

Making a request to GET /orders/1?_expand=customer, will return something like:

[
  {
    "id": 1,
    "product": "Apples",
    "quantity": 5,
    "customerId": 1,
    "customer": {
      "id": 1,
      "name": "Sample Customer",
      "address": "1 The Street",
    }
  }
]

One final tip

Not everything has to be a collection in the database.

Notice that you defined customers and orders as empty arrays, which means they act as a REST collection using an id field to get individual items.

You don't have to, though. You can also specify a simple object, which can be handy for things like configuration.

So by changing the db.json file to the following, you can get to your configuration using the /config endpoint:

{
    "customers":[
        {
            "id": 1,
            "name": "Sample Customer",
            "address": "1 The Street"
        }
    ],
    "orders":[],
    "discounts":[],
    "config": {
        "googleAPIKey":"XXXXX-1",
        "someConfigKey":"ABCD-1122"
    }
}

That's especially handy if you need different configuration depending on who you are demonstrating your app to.

Useful yet so simple

That was a just a brief run-through of some of the basics. There is also the ability to sort and slice the data (think paging), more details of which can be found on the GitHub page.

Despite the title of this post, this obviously doesn't just apply to Angular of course - anywhere you need a fake REST API.

Hopefully, you can see how useful JSON Server is to have on your tools list.