1

I'm new use nodejs and mongodb, now I build restful API use nodejs and mongodb. I want use response standard for my API with http://jsonapi.org standard.

I need a suggestion from advance how best way to do it, making my API response like the following JSON data:

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "links": {
    "self": "http://example.com/users"
  },
  "data": [{
    "type": "users",
    "id": 5b647bb8998248235a0aab3c,
    "attributes": {
      "username": "luke",
      "email": "[email protected]",
      "password": "password",
      "hashpassword":"",
      "oldpassword":"$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
      "salt":"2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
      "usertype":"bisnis",
      "userstatus":"not aktif"
    }
  }, {
    "type": "users",
    "id": 5b647bdf998248235a0aab3d,
    "attributes": {
      "username": "ken",
      "email": "[email protected]",
      "password": "password",
      "hashpassword":"",
      "oldpassword":"$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
      "salt":"2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
      "usertype":"bisnis",
      "userstatus":"not aktif"
    }
  }]
}

I have problem with nest iteration when create output as above. This my code:

const UsersModel = mongoose.model('Users');

//...show list user
exports.listUsers = (req, res) => {
  UsersModel.find({}, (err, result) => {
    if (err) {
      res.send({code: 400, failed: 'Error 400'});
    }
    res.json(result);
  });
};

And this is my result JSON:

[
    {
        "type": "users",
        "userstatus": "not aktif",
        "_id": "5b647bb8998248235a0aab3c",
        "username": "luke",
        "email": "[email protected]",
        "password": "password",
        "usertype": "bisnis",
        "hashpassword": "$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
        "salt": "2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
        "__v": 0
    },
    {
        "type": "users",
        "userstatus": "tidak aktif",
        "_id": "5b647bdf998248235a0aab3d",
        "username": "ken",
        "email": "[email protected]",
        "password": "password",
        "usertype": "personal",
        "hashpassword": "$2a$10$hok988mszyIBiXVNjmfifOiPNzXkBRRRynXJS/0qCkvlaBOQs65MO",
        "salt": "IiMvtVYVqTpZFXmYQIM4IlS6PJFVZ3kw",
        "__v": 0
    }
]

And this is my temporary code for my problem.

//...show list user
exports.listUsers = (req, res) => {
    UsersModel.find({}, (err, result) => {
      if (err) {
        res.send({code: 400, failed: 'Error 400'});
      }

      let listData  = [];

      for (let key in result) {
        let data = {};
        let attr = {};

        if (result.hasOwnProperty(key)) {
          data.type = result[key].type;
          data.id = result[key]._id;

          for(let i in result[key]) {

            if(result[key].hasOwnProperty(i)) {
              attr.username = result[key].username;
              attr.email = result[key].email;
              attr.password = result[key].password;
              attr.hashpassword = result[key].hashpassword;
              attr.oldpassword = result[key].oldpassword;
              attr.salt = result[key].salt;
              attr.usertype = result[key].usertype;
              attr.userstatus = result[key].userstatus;
            }
          }

          data.attribute = attr;
          listData.push(data);
        }

      }

      let collections = {
        "meta": {
          "copyright": "Copyright 2018 Kotakku Studio and Lab",
          "authors": [
            "sw. saputra"
          ]
        },
        "link": {
          "self": req.protocol + '://' + req.get('host') + req.originalUrl
        },
        "data": listData
      }

      res.json(collections);
    });
};

Please give me suggestion the elegant and the best way to solve my problem if my temporary code is not correct.

Thanks advance.

1
  • 1
    You can use map function and extract all the code from the find callback. you can apply the map function to the result variable and remove the for, because the map function iterates over the entire array. Look at the map documentation developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Aug 4, 2018 at 14:06

3 Answers 3

1

You need to create a proper mongoose schema according to your requirement and map the res to the schema.

//Schema for users
var UsersSchema = mongoose.Schema({
 links: {
   self: String 
 },
  data:[{
    type: String,
    attributes: {
      username: String,
      .
      .
      .
    }
  }]
})

id for each document in an array will be created automatically by MongoDB. For mongoose schema docs see http://mongoosejs.com/docs/guide.html You can also check this simple TODO API for reference https://github.com/mkujaggi/node-course-todo-api

Sign up to request clarification or add additional context in comments.

Comments

1

In this condition's statement:

if(result[key].hasOwnProperty(i)) {

You should be accessing the i of result[key]:

        if(result[key].hasOwnProperty(i)) {
          attr.username = result[key][i].username;
          attr.email = result[key][i].email;
          attr.password = result[key][i].password;
          attr.hashpassword = result[key][i].hashpassword;
          attr.oldpassword = result[key][i].oldpassword;
          attr.salt = result[key][i].salt;
          attr.usertype = result[key][i].usertype;
          attr.userstatus = result[key][i].userstatus;
        }

And you don't need all those .hasOwnProperty checks unless you're modifying native prototypes, which you probably shouldn't. And especially for the Array, it's not necessary if you'd just loop properly with a for instead of a for-in.

exports.listUsers = (req, res) => {
UsersModel.find({}, (err, result) => {
    if (err) {
      res.send({
        code: 400,
        failed: 'Error 400'
      });
    }

    let listData = [];

    let data = {};
    let attr = {};

    data.type = result[key].type;
    data.id = result[key]._id;

    for (let i = 0; i < result[key].length; i++) {

        attr.username = result[key][i].username;
        attr.email = result[key][i].email;
        attr.password = result[key][i].password;
        attr.hashpassword = result[key][i].hashpassword;
        attr.oldpassword = result[key][i].oldpassword;
        attr.salt = result[key][i].salt;
        attr.usertype = result[key][i].usertype;
        attr.userstatus = result[key][i].userstatus;
    }

    data.attribute = attr;
    listData.push(data);
  }

}

let collections = {
  "meta": {
    "copyright": "Copyright 2018 Kotakku Studio and Lab",
    "authors": [
      "sw. saputra"
    ]
  },
  "link": {
    "self": req.protocol + '://' + req.get('host') + req.originalUrl
  },
  "data": listData
}

res.json(collections);
});
};

1 Comment

Oh, I didn't notice that the array is at the top level of the JSON response. The outer loop should be removed.
1

I would do something like this with iterating over the keys (this will work dynamically that is even if we don't know key names)

var test=[
    {
        "type": "users",
        "userstatus": "not aktif",
        "_id": "5b647bb8998248235a0aab3c",
        "username": "luke",
        "email": "[email protected]",
        "password": "password",
        "usertype": "bisnis",
        "hashpassword": "$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
        "salt": "2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
        "__v": 0
    },
    {
        "type": "users",
        "userstatus": "tidak aktif",
        "_id": "5b647bdf998248235a0aab3d",
        "username": "ken",
        "email": "[email protected]",
        "password": "password",
        "usertype": "personal",
        "hashpassword": "$2a$10$hok988mszyIBiXVNjmfifOiPNzXkBRRRynXJS/0qCkvlaBOQs65MO",
        "salt": "IiMvtVYVqTpZFXmYQIM4IlS6PJFVZ3kw",
        "__v": 0
    }
]
var listData=[]
test.forEach((obj)=>{
   var tempObj={attributes:{}}; //initialize tempObj
   Object.keys(obj).forEach((key)=>{
     if(key=="_id" || key=="type"){
      tempObj[key]=obj[key];
     }else{
      tempObj.attributes[key]=obj[key];
      }
   })
   listData.push(tempObj);
})

let collections = {
        "meta": {
          "copyright": "Copyright 2018 Kotakku Studio and Lab",
          "authors": [
            "sw. saputra"
          ]
        },
        "link": {
          "self": 'test url'
        },
        "data": listData
      }
console.log(collections)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.