Search code examples
restjson-server

POST collection of objects in json-server


I am using json-server to fake the Api for the FrontEnd team.

We would like to have a feature to create the multiple objects (Eg. products) in one call.

In WebApi2 or actual RestApis, it can be done like the following:

POST api/products //For Single Creation
POST api/productCollections  //For Multiple Creation

I don't know how I can achieve it by using json-server. I tried to POST the following data to api/products by using the postman, but it does not split the array and create items individually.

[
    {
        "id": "ff00feb6-b1f7-4bb0-b09c-7b88d984625d",
        "code": "MM",
        "name": "Product 2"
    },
    {
        "id": "1f4492ab-85eb-4b2f-897a-a2a2b69b43a5",
        "code": "MK",
        "name": "Product 3"
    }
]

It treats the whole array as the single item and append to the existing json.

Could you pls suggest how I could mock bulk insert in json-server? Or Restful Api should always be for single object manipulation?


Solution

  • This is not something that json-server supports natively, as far as I know, but it can be accomplished through a workaround.

    I am assuming that you have some prior knowledge of node.js

    You will have to create a server.js file which you will then run using node.js. The server.js file will then make use of the json-server module.

    I have included the code for the server.js file in the code snippet below.

    I made use of lodash for my duplicate check. You will thus need to install lodash. You can also replace it with your own code if you do not want to use lodash, but lodash worked pretty well in my opinion.

    The server.js file includes a custom post request function which accesses the lowdb instance used in the json-server instance. The data from the POST request is checked for duplicates and only new records are added to the DB where the id does not already exist. The write() function of lowdb persists the data to the db.json file. The data in memory and in the file will thus always match.

    Please note that the API endpoints generated by json-server (or the rewritten endpoints) will still exist. You can thus use the custom function in conjunction with the default endpoints.

    Feel free to add error handling where needed.

    const jsonServer = require('json-server');
    const server = jsonServer.create();
    const _ = require('lodash')
    const router = jsonServer.router('./db.json');
    const middlewares = jsonServer.defaults();
    const port = process.env.PORT || 3000;
        
    server.use(middlewares);
    server.use(jsonServer.bodyParser)
    server.use(jsonServer.rewriter({
        '/api/products': '/products'
    }));
        
    server.post('/api/productcollection', (req, res) => {
        const db = router.db; // Assign the lowdb instance
        
        if (Array.isArray(req.body)) {
            req.body.forEach(element => {
                insert(db, 'products', element); // Add a post
            });
        }
        else {
            insert(db, 'products', req.body); // Add a post
        }
        res.sendStatus(200)
        
        /**
         * Checks whether the id of the new data already exists in the DB
         * @param {*} db - DB object
         * @param {String} collection - Name of the array / collection in the DB / JSON file
         * @param {*} data - New record
         */
        function insert(db, collection, data) {
            const table = db.get(collection);
            if (_.isEmpty(table.find(data).value())) {
                table.push(data).write();
            }
        }
    });
        
    server.use(router);
    server.listen(port);
    

    If you have any questions, feel free to ask.