1

I have data stored in a variable like this

var products = [
    {
        place1:[
            {id: 1, name: "choc1", price: 20},
            {id: 2, name: "choc2", price: 30}
        ],
        place2:[
            {id: 1, name: "coffee", price: 50}
        ],
        place3: [
            {id: 1, name: "oil1", price: 10},
            {id: 2, name: "oil2", price: 60},
            {id: 3, name: "oil3", price: 70}
        ]
    }
];

I want to write a get method, such that it responds to this Url

http://myurl.com/place1/1

the get method is of the format

router.get('/:place/:id([0-9]{1,})', function(req, res){
//  send the exact data as requested
}

What I don't understand is how do I validate the link. i.e., verify if the place is in the products variable, then verify if the id is present in that product variable and then if present, send it back to the server, else send an error response.

0

4 Answers 4

1

Here is the function to get nested value from object using dot notation:

/**
 * Treating field name with dot in it as a path to nested value.
 * For example 'settings.day' is path to { settings: { day: 'value' } }
 *
 * @param {{}} object Object where to look for a key
 * @param {string} field Dot notated string, which is path to desired key
 * @returns {*}
 */
getNestedValue = function (object, field) {
    if (!object) {
        return null;
    }

    var path   = field.split('.');
    while (path.length && (object = object[path.shift()]));

    return object;
};
Sign up to request clarification or add additional context in comments.

2 Comments

Could you please explain it in a bit more detail, in context with the question, since I am not sure I understand how to apply this
Sorry, my bad, misread your data structure. My approach would work if your place1 would be an object like this { id_1: { id:1, name: 'oil1' }, id_2: { id:1, name: 'oil2' }} Then you would be able to do like this getNestedValue(products[0], [req.params.place, 'id_'+req.params.id].join('.'))
0
if (products[0][req.params.place] === undefined)
  console.log("place doesnt exist");
else {
    if (products[0][req.params.place][req.params.id - 1] === undefined)
        console.log ("id doesnt exist");
    else {
        ....
    }
}

8 Comments

Don't use -1, it is very possible, that ids will be 456,457,458 instead of 1,2,3. OP will need to iterate through the array of products to check if desired id is there.
i get an error that the place variable doesn't exist
then it doesn't exist in your products, see this, change place to "place1" and click run
the structure is exactly as mentioned in the question. in req.params.places, it says unresolved variable place.
inside your router, can you log req.params.place? what do you see?
|
0

Here is how you can access the nested JSON object:

if(products[0][req.params.place]) {
    var place = products[0][req.params.place];
    var resSent = false;
    for(var obj in place) {
        if(place[obj].id == req.params.id) {
            resSent = true;
            res.send(place[obj]);
        }
    }
    if(!resSent) {
        res.send(new Error('Not Found'));
    }
} else {
    res.send(new Error('Not Found'));
}

Comments

0

Here is the start of a router. I ran out of time to work on the filtering of the products as the structure is a little weird. If you use this as a base you will need to make some slight mods to use the req and res objects in node, but the regex is sound.

EDIT.. looks like you changed the url reg, I'll leave it to you to figure out how to replace a :capture with the appropriate regex if none is specified like in the previous pattern eg. :id(RegEx)

Please see inline comments below for how it works.

// convert the search string into regEx string and captures from string
const regexify = str => ({
  captures: str.match(/:([a-z]+)/g).map(x => x.replace(':', '')),
  reg: '^' + str.replace(/\//g, '\\/').replace(/:\w+/g, '') + '$'
})

const parse = x => parseInt(x) == x ? parseInt(x) : x

class Router {
  constructor(object) {
    this.routes = []
    this.__onError = console.error.bind(console)
  }
  get(uri, cb) {
    const { captures, reg } = regexify(uri)
    // create a new route
    this.routes.push({
      cb,
      reg: new RegExp(reg),
      captures
    })
    return this
  }
  error(cb) {
    this.__onError = cb
  }
  exec(uri/*, req, res*/) {
    // find a matching route
    const route = this.routes.find(x => x.reg.test(uri))
    
    if (!route) {
      return this.__onError(`could not find route: ${uri}`)
    }
    
    const params = uri
      .match(route.reg)                     // get the params from the url
      .slice(1, route.captures.length + 1)  // remove unwanted values
      .map(parse)                           // parse numbers
      
    // call the route callback with the correct params injected
    route.cb(
      /*req,
      res,*/
      ...params
    )
  }
}

// instantiate the router
const router = new Router

// create router methods
router.get('/:place([a-z0-9]+)/:id([0-9]{1,})', (/*req, res, */place, id) => {
  console.log(
    'first route callback:',
    place, id
  )
})

router.get('/:place([a-z0-9]+)', (/*req, res, */place) => {
  console.log(
    'second route callback:',
    place
  )
})

router.error(err => {
  console.error(err)
})
// run the router on request
router.exec('/place1/1'/*req, res */)

// proof of concept below
router.exec('/place1'/*req, res */)
router.exec('/1/fail'/*req, res */)

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.