Json-server: How to wrap responses?

Created on 12 Jun 2015  路  14Comments  路  Source: typicode/json-server

Hi, thanks for your wonderful json server.

I was wondering if it is possible to modify the server response. For example, if I get /posts currently I receive an array of posts. I would like to receive an object with one property posts and the list of post as the value of the property:

{ posts: [ /* list of posts here */ ] }

I have been playing with the middleware but I can't hijack the server response. Any clues?

Most helpful comment

Hi @csibar

This code should do the job

var jsonServer = require('json-server')

var server = jsonServer.create()
var router = jsonServer.router('db.json')

server.use(jsonServer.defaults)
server.use(router)

// If you want to target /posts specifically
router.render = function (req, res) {
  if (req.url === '/posts') {
    res.jsonp({
      posts: res.locals.data
    })
  } else {
    res.jsonp(res.locals.data)
  }
}

// Or /resources in general
router.render = function (req, res) {
  if (req.method === 'GET' && !req.params.id) {
    var obj = {}
    obj[req.params.resource] = res.locals.data
    res.jsonp(obj)
  } else {
    res.jsonp(res.locals.data)
  }
}

server.listen(3000)

All 14 comments

Hi @arqex, thanks for the nice words :)
Right now you can't, but I plan to release something this week.

Hi,

That is really good news. I tweaked json-server locally in order to get it working as I need, but something official is much better :)

Thanks

Just did a quick release (v0.7.15).

You can now override the new router.render method to customize the response. Here's a test showing how it can be used:
https://github.com/typicode/json-server/blob/v0.7.15/test/index.js#L392

You can access data before it's returned to the browser using res.locals.data.

I'll add it to the README later.

Feedbacks are welcome :)

Hi typicode,

I looks great, a simple proxy function, not only for wrapping the data, but for customizing the reponse before it is sent. Perfect.

Thanks for your awesome work!

Hi @arqex, You're welcome. I'm happy if it helps.

Hi, could you please help me out with a simple tutorial on how to wrap the /posts response's array with a { posts : [ ]} object? I'm a little bit confused. Thanks.

Hi @csibar

This code should do the job

var jsonServer = require('json-server')

var server = jsonServer.create()
var router = jsonServer.router('db.json')

server.use(jsonServer.defaults)
server.use(router)

// If you want to target /posts specifically
router.render = function (req, res) {
  if (req.url === '/posts') {
    res.jsonp({
      posts: res.locals.data
    })
  } else {
    res.jsonp(res.locals.data)
  }
}

// Or /resources in general
router.render = function (req, res) {
  if (req.method === 'GET' && !req.params.id) {
    var obj = {}
    obj[req.params.resource] = res.locals.data
    res.jsonp(obj)
  } else {
    res.jsonp(res.locals.data)
  }
}

server.listen(3000)

Hi, thank you very much, now I get it, but it throws an error:

Loading database from server.js

/usr/lib/node_modules/json-server/bin/index.js:156
  var object = require(process.cwd() + '/' + source)()
                                                    ^
TypeError: object is not a function
    at Object.<anonymous> (/usr/lib/node_modules/json-server/bin/index.js:156:53)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

I think it's because your js file doesn't export a function. You can use the README example as a starting point:

module.exports = function() {
  var data = { users: [] }

  // Create 1000 users
  for (var i = 0; i < 1000; i++) {
    data.users.push({ id: i, name: 'user' + i })
  }

  return data
}

If you need help with that or if it doesn't work, you can paste your server.js.

Oh OK, my bad, works like a charm, thank you very much!

One more thing: req.params.resource at obj[req.params.resource] = res.locals.data returns undefined, so your second piece of code (to wrap all responses in general) doesn't work. I mean, it does, but it puts undefined to the JSON response.

Oh sorry about that, thanks for letting me know. I've not tested code.
Did you manage to get it work?

Unfortunately no, req.params returns just the path, tried to replace the slash/slashes by regexp, but it's not an elegant way. Do you have a solution for this?

@typicode Hi, Great package! Thanks!
Is running by module the only way to simply customize the response?
For example if I wanted the POST, PUT, and DELETE to respond with:

{ 
   success: true/false, // based on the result of the operation
   data: res.locals.data
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

AdamCook44 picture AdamCook44  路  3Comments

goldmont picture goldmont  路  3Comments

sharpmachine picture sharpmachine  路  4Comments

pantchox picture pantchox  路  3Comments

shikaan picture shikaan  路  3Comments