2

I am trying to replace values in a string with the comparable jSON property in an object.

var value = "/sessions/:sessionId/events/:id";
var result = replace(value, { sessionId : 1 , id : 23 });

// result : "/sessions/1/events/23"
console.log(result);

Is it possible with JavaScript (I'm sure it is)? Not sure about the most efficient way to do this and how to handle it when all the values inside the template string are not matched.

Thanks in advance.

Update (Solution)

var url = function (template, parameters) {

    var extra = [];

    for (param in parameters) {
        if (value.indexOf(param) < 0) {
            extra.push(param + '=' + parameters[param]);
        }
    }

    var result = template.replace(/:(\w+)/g, function (substring, match) {
        var routeValue = parameters[match];
        if (!routeValue) {
            throw "missing route value for " + match + ' in "' + template +'"';
        }
        return routeValue;
    });

    if (result.indexOf("/:") > 0) {
        throw "not all route values were matched";
    }

    return (extra.length === 0) ? result : result + "?" + extra.join("&");
};

var value = "/sessions/:sessionId/events/:id";
var data = {
    sessionId: 1,
    id: 23,
    term: "butter"
};

// result : /sessions/1/events/21?term=butter
console.log(url(value, data));
2
  • 2
    That's not JSON. It's a JavaScript object. JSON is a string representation of data that just so happens to very closely resemble JavaScript syntax. It's onlY JSON if it's a string. { sessionId : 1 , id : 23 } is an object literal, '{"sessionId": 1, "id": 23}' (a string) is JSON. Commented Jul 24, 2013 at 15:36
  • The template url format is similar to AngularJs $resource url template, looking at github.com/angular/angular.js/blob/master/src/ngResource/… setUrlParams() does the magic and also handles url encoding. Commented Jul 24, 2013 at 19:13

3 Answers 3

6

A regex would work just fine here.

var value = "/sessions/:sessionId/events/:id";
var obj = { sessionId : 1 , id : 23 };

var result = value.replace(/:(\w+)(\/|\b)/g, function(substring, match, nextMatch){
    return obj[match] + nextMatch;
});
Sign up to request clarification or add additional context in comments.

3 Comments

is there a way to count how many of the values with the ":" were not matched? I'd like to throw an error if not all spots were replaced. I could probably just do a search for ":".
Also why match the "/" after the section? removing that still works.
@KhalidAbuhakmeh: You could add an if(!obj[match]){ failures++; } in the callback. I'm matching the /, because.... I don't know. I guess you could remove it :)
3

Assuming you have the following javascript object:

var myObject = { sessionId : 1 , id : 23 };

you can loop each property and do a replace on the original string...

var value = "/sessions/:sessionId/events/:id";

for(var item in myObject){
    value = value.replace(item, myObject[item]);
}

//value = "/sessions/:1/events/:23"

Here is a working example

It is not clear if you want to keep the : characters or not. If not, then you can just include that in your replace function:

value = value.replace(':' + item, myObject[item]);

Checking for missing parameters

If you have any extra values in your object that do not exist in your input string, then they will not have any effect. If however, you want to take action if one of the items is not found in the original string, then you can do a check in the loop:

var noMatch = false;
for(var item in myObject){
    if(value.indexOf(item) < 0){
        noMatch = true;
    }
    value = value.replace(item, myObject[item]);
}
if(noMatch){
    //something is wrong!
}

Dealing with JSON

If you do actually have a JSON string to begin with, you can convert that to an object with the following:

var jsonString = '{"sessionId": 1, "id": 23}';
var myObject = JSON.parse(jsonString);

3 Comments

thanks musefan, I really liked this answer too, but I liked the simplicity of the other one as well.
@KhalidAbuhakmeh: Personally I think my solution is more simple. Mine is also much more efficient
yeah you make a good point, I'll probably tweak it. I wish I could give both of you the checkmark. StackOverflow needs a split bounty.
1

here is another way of doing it.

http://jsfiddle.net/rayweb_on/suHej/

 var value = "/sessions/:sessionId/events/:id";
 var source = { sessionId : 1 , id : 23 };
 var result = value.replace(":sessionId",source.sessionId);
 var result = result.replace(":id",source.id);
 console.log(result);

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.