我有一个这样的字符串:

abc=foo&def=%5Basf%5D&xyz=5

如何将其转换为这样的JavaScript对象?

{
  abc: 'foo',
  def: '[asf]',
  xyz: 5
}

当前回答

我还需要在URL的查询部分处理+ (decodeURIComponent没有),所以我改编了Wolfgang的代码成为:

var search = location.search.substring(1);
search = search?JSON.parse('{"' + search.replace(/\+/g, ' ').replace(/&/g, '","').replace(/=/g,'":"') + '"}',
             function(key, value) { return key===""?value:decodeURIComponent(value)}):{};

在我的例子中,我使用jQuery来获得URL准备好的表单参数,然后这个技巧来构建一个对象,然后我可以轻松地更新对象上的参数并重新构建查询URL,例如:

var objForm = JSON.parse('{"' + $myForm.serialize().replace(/\+/g, ' ').replace(/&/g, '","').replace(/=/g,'":"') + '"}',
             function(key, value) { return key===""?value:decodeURIComponent(value)});
objForm.anyParam += stringToAddToTheParam;
var serializedForm = $.param(objForm);

其他回答

在2021年…请认为这是过时的。

Edit

这个编辑改进并解释了基于评论的答案。

var search = location.search.substring(1);
JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')

例子

分五个步骤解析abc=foo&def=%5Basf%5D&xyz=5:

decodeURI: abc = foo&def = xyz (asf) = 5 转义引号:相同,因为没有引号 替换&:abc=foo","def=[asf]","xyz=5 " 5 . Replace =: abc":"foo","def":"[asf]","xyz": Suround卷曲和引用:{“abc”:“foo”、“def”:“(asf)”,“xyz”:“5”}

这是合法的JSON。

改进的解决方案允许搜索字符串中有更多字符。它使用了一个恢复函数来进行URI解码:

var search = location.search.substring(1);
JSON.parse('{"' + search.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) })

例子

search = "abc=foo&def=%5Basf%5D&xyz=5&foo=b%3Dar";

给了

Object {abc: "foo", def: "[asf]", xyz: "5", foo: "b=ar"}

原来的答案

一行程序:

JSON.parse('{"' + decodeURI("abc=foo&def=%5Basf%5D&xyz=5".replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}')

我也遇到了同样的问题,尝试了这里的解决方案,但没有一个真正有效,因为我在URL参数中有数组,像这样:

?param[]=5&param[]=8&othr_param=abc&param[]=string

所以我最终写了我自己的JS函数,它使一个数组的参数在URI:

/**
 * Creates an object from URL encoded data
 */
var createObjFromURI = function() {
    var uri = decodeURI(location.search.substr(1));
    var chunks = uri.split('&');
    var params = Object();

    for (var i=0; i < chunks.length ; i++) {
        var chunk = chunks[i].split('=');
        if(chunk[0].search("\\[\\]") !== -1) {
            if( typeof params[chunk[0]] === 'undefined' ) {
                params[chunk[0]] = [chunk[1]];

            } else {
                params[chunk[0]].push(chunk[1]);
            }


        } else {
            params[chunk[0]] = chunk[1];
        }
    }

    return params;
}

/** * Parses and builds Object of URL query string. * @param {string} query The URL query string. * @return {!Object<string, string>} */ function parseQueryString(query) { if (!query) { return {}; } return (/^[?#]/.test(query) ? query.slice(1) : query) .split('&') .reduce((params, param) => { const item = param.split('='); const key = decodeURIComponent(item[0] || ''); const value = decodeURIComponent(item[1] || ''); if (key) { params[key] = value; } return params; }, {}); } console.log(parseQueryString('?v=MFa9pvnVe0w&ku=user&from=89&aw=1')) see log

对于Node JS,你可以使用Node JS API querystring:

const querystring = require('querystring');

querystring.parse('abc=foo&def=%5Basf%5D&xyz=5&foo=b%3Dar');
// returns the object

文档:https://nodejs.org/api/querystring.html

许多其他的解决方案没有考虑到边界情况。

这个可以处理

空键a=1&b=2& 空值a=1&b 空值a=1&b= 未编码的等号a=1&b=2=3=4

  decodeQueryString: qs => {
    // expects qs to not have a ?
    // return if empty qs
    if (qs === '') return {};
    return qs.split('&').reduce((acc, pair) => {
      // skip no param at all a=1&b=2&
      if (pair.length === 0) return acc;
      const parts = pair.split('=');
      // fix params without value
      if (parts.length === 1) parts[1] = '';
      // for value handle multiple unencoded = signs
      const key = decodeURIComponent(parts[0]);
      const value = decodeURIComponent(parts.slice(1).join('='));
      acc[key] = value;
      return acc;
    }, {});
  },