0

I am developing a general function inside a solution which would replace /endpoint/{item.id}/disable/{item.name} with /endpoint/123/disable/lorem where I pass the function the URL and item.

The item would be an object with keys id and name.

What would be the best way to find items with the structure {item.KEY} and replacing them with item.KEY?

5
  • When you say "structure", do you mean "sub-string"? Commented Jul 29, 2016 at 10:39
  • @this-vidor Exactly, sorry forgot the right term Commented Jul 29, 2016 at 10:44
  • Template literals Commented Jul 29, 2016 at 10:47
  • @Andreas I cannot use ES6, sorry Commented Jul 29, 2016 at 10:53
  • @Andreas That doesn't really apply in this case; OP is receiving the "template" string ready-made, and has to match the pattern {item.KEY} in it. Commented Jul 29, 2016 at 10:55

2 Answers 2

2

the best way to solve this is passing a function to handle a regex. I modified your parameters to make the mapping easier- I'm sure you can change this on your own if necessary

var url = '/endpoint/{id}/disable/{name}'; //I modified your parameters

var definition = { id: 123, name: 'lorem' };
url = url.replace(/{([^}]*)}/g, function (prop) {
  var key = prop.substr(1, prop.length - 2);
  if (definition[key])
    return encodeURIComponent(definition[key]);
  else
    throw new Error('missing required property "' + key + '" in property collection');
});

//alert(url);

fiddle: https://jsfiddle.net/wovr4ct5/2/

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

3 Comments

Thank you, that was exactly what I was looking for.
Should I use definition[key] or definition.hasOwnProperty(key) for the if?
@AnžeJenšterle this depends on your "definition" object. If definition is an instance of a class, has properties defined using Object.defineProperties or is derived from another class you should used hasOwnProperty but in this case it doesn't make any difference
1

If you don't want to use eval, maybe use something like this:

var item = {
    id: 123,
    KEY: "lorem"
};

function pick(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
        } else {
            return;
        }
    }
    return o;
}

and then

str.replace(/{.*?}/g, function(match){ // match {...}
    var path = match.substring(1,match.length-1); // get rid of brackets.
    return pick(scope, path); //get value and replace it in string.
});

9 Comments

This seems like exactly the kind of situation where using eval would be super-dangerous. Good chance that wherever these strings are coming from, they haven't been sanitized.
A much safer solution would be to supply path.split('.')[1] as a key to the item object. :) Will change down-vote to up-vote if you avoid eval in your solution.
It is not clear what pick is supposed to accomplish. You're returning a reference to the global context? What is happening! path is already a string of the format item.key. How does pick improve on the single line in my previous comment?
Oh, I see, you just copy-pasted from the linked solution. Sorry, but that's serious overkill. Down-vote remains, because you are still advocating eval in a (probably) unsafe context.
Also, maybe you misunderstand the code you've pasted? What makes you think this string-based lookup should be performed on window?
|

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.