开发者

Exempting characters in an escaped string

I have a little function that makes URL arguments out of an object:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        ret += i + '=' + escape(o[i]) + '&';
    }
    return ret.substr(0, ret.length - 1);
}

which I then can call like this:开发者_JS百科

MkArgs({
    protocol: 'wsfederation',
    realm: 'https://www.x.com/',
    fedRes: 'Home/FederationResult',
    context: '~/Home/FAQ',
    version: '1.0',
    callback: '?'
});

to produce the following:

?protocol=wsfederation&realm=https%3A//www.x.com/&fedRes=Home/FederationResult&context=%7E/Home/FAQ&version=1.0&callback=%3F

everything is fine except that I don't want the last argument escaped i.e. I want:

callback=?

instead of

callback=%3F

is there any way I can indicate that within the string? I tried '\?' but that doesn't do it and haven't found any references as to how to protect a piece of string from escaping...

  • e


The MkArgs function is your own; change it to include an escape mechanism. I would advise against using backslash, though. If this is just your own code, perhaps it would be enough to put in a hackish special case.


That's a pretty special case. Maybe you should change your function:

function MkArgs(o, isJSONP) {
    var ret = '?';
    for (var i in o) {
        var val = o[i];
        val = escape(val);
        ret += i + '=' + val + '&';
    }
    return ret.substr(0, ret.length - 1) + isJSONP ? '&callback=?':'';
}

and call it:

MkArgs({
  protocol: 'wsfederation',
  realm: 'https://www.x.com/',
  fedRes: 'Home/FederationResult',
  context: '~/Home/FAQ',
  version: '1.0'
}, true);


The escape or encodeURIComponent functions don't have any way of "skipping" certain characters. So, all you can do is to either avoid calling the encode function when you don't want to or replace the chars you don't want encoded, call encode and then put the original chars back again.

If you want to skip escaping the whole value for a particular key, you can just check for the particular keys that you don't want to escape and handle appropriately like this:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        var val = o[i];
        if (i != "callback") {
            val = encodeURIComponent(val);
        }
        ret += i + '=' + val + '&';
    }
    return ret.substr(0, ret.length - 1);
}

If you want to skip just certain characters, then you can replace them with some unique sequence, escape and then put them back:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        var val = o[i];
        if (i == "callback") {
            val = val.replace(/\?/, "--xx--");  // replace with unique sequence
            val = encodeURIComponent(val);
            val = val.replace(/--xx--/, "?");   // put orig characters back
        } else {
            val = encodeURIComponent(val);
        }
        ret += i + '=' + val + '&';
    }
    return ret.substr(0, ret.length - 1);
}

FYI, note I've switched to using encodeURIComponent() which is recommended over the deprecated escape() because escape() doesn't work for non-ascii characters.


thanks everyone for the replies. what I ended up doing was:

function MkArgs(o) {
    var ret = '?';
    for (var i in o) {
        ret += i;
        if (o[i]) ret += '=' + escape(o[i]);
        ret += '&';
    }
    return ret.substr(0, ret.length - 1);
}

then calling it like:

MkArgs({
    protocol: 'wsfederation',
    realm: 'https://www.x.com/',
    fedRes: 'Home/FederationResult',
    context: '~/Home/FAQ',
    version: '1.0',
    'callback=?': null
});

that way I don't rely on the values but the keys to make the distinction. not really pretty but it's the best I could think of


function MkArgs(o) {
    var ret = '?';
    var lastEl = '';
    for (var i in o) {
        ret += i + '=' + escape(o[i]) + '&';
        lastEl = o[i];
    }
    return ret.substr(0, ret.length - 1 - lastEl.length) + lastEl;
}

this works for the last element in the object.

EDIT: It seems that in a classic for in loop, javascript does not have a precise order in which it loops over the object props, so the above solution is not guaranteed to work.
In this case you have 2 solutions :

  • If you know which property you want to "protect" from escaping, you should check for that prop in the loop and specifically not escape it :

    for (var i in o) {
         if(i=="myProp")
         // unescape
         else
         // escape
    }
    
  • If you do not now the property, but you want only the last one added into the query, you can do something like this (after building the query) :

    var q = MkArgs(o);
    var parts = q.split('=');
    var toUnescape = parts[parts.length-1];
    q = q.substring(0,q.length - toUnescape.length) + unescape(toUnescape);
    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜