我有一个这样的字符串:

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

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

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

当前回答

一个班轮。干净简单。

const params = Object.fromEntries(new URLSearchParams(location.search));

对于您的具体情况,它将是:

const str = 'abc=foo&def=%5Basf%5D&xyz=5'; const params = Object.fromEntries(new URLSearchParams(str)); console.log (params);

其他回答

我也遇到了同样的问题,尝试了这里的解决方案,但没有一个真正有效,因为我在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;
}

如果你正在使用URI.js,你可以使用:

https://medialize.github.io/URI.js/docs.html#static-parseQuery

var result = URI.parseQuery("?foo=bar&hello=world&hello=mars&bam=&yup");
result === {
  foo: "bar",
  hello: ["world", "mars"],
  bam: "",
  yup: null
};

在&上拆分以获得名称/值对,然后在=上拆分每对。这里有一个例子:

var str = "abc=foo&def=%5Basf%5D&xy%5Bz=5"
var obj = str.split("&").reduce(function(prev, curr, i, arr) {
    var p = curr.split("=");
    prev[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
    return prev;
}, {});

另一种方法,使用正则表达式:

var obj = {}; 
str.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) {
    obj[decodeURIComponent(key)] = decodeURIComponent(value);
}); 

本文改编自约翰·瑞西格的《搜索和不替换》。

2022 ES6/7/8,进近

从ES6开始,Javascript提供了几个构造来为这个问题创建一个性能解决方案。

这包括使用URLSearchParams和迭代器

let params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
params.get("abc"); // "foo"

如果你的用例需要你实际将其转换为对象,你可以实现以下函数:

function paramsToObject(entries) {
  const result = {}
  for(const [key, value] of entries) { // each 'entry' is a [key, value] tupple
    result[key] = value;
  }
  return result;
}

基本的演示

const urlParams = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
const entries = urlParams.entries(); //returns an iterator of decoded [key,value] tuples
const params = paramsToObject(entries); //{abc:"foo",def:"[asf]",xyz:"5"}

使用Object.fromEntries和spread

我们可以使用Object.fromEntries,用Object.fromEntries(entries)替换paramsToObject。

对象的列表名称-值对是要遍历的值对 键是名称,值是值。

由于URLParams返回一个可迭代对象,使用展开操作符而不是调用.entries也将根据其规范生成条目:

const urlParams = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
const params = Object.fromEntries(urlParams); // {abc: "foo", def: "[asf]", xyz: "5"}

注意:根据URLSearchParams规范,所有值都是自动字符串

多个相同的键

正如@siipe指出的,包含多个相同键值的字符串将被强制转换为最后一个可用值:foo=first_value&foo=second_value本质上将变成:{foo: "second_value"}。

根据这个答案:https://stackoverflow.com/a/1746566/1194694没有规范来决定用它做什么,每个框架可以有不同的行为。

一个常见的用例是将两个相同的值连接到一个数组中,使输出对象变成:

{foo: ["first_value", "second_value"]}

这可以通过以下代码实现:

const groupParamsByKey = (params) => [...params.entries()].reduce((acc, tuple) => {
 // getting the key and value from each tuple
 const [key, val] = tuple;
 if(acc.hasOwnProperty(key)) {
    // if the current key is already an array, we'll add the value to it
    if(Array.isArray(acc[key])) {
      acc[key] = [...acc[key], val]
    } else {
      // if it's not an array, but contains a value, we'll convert it into an array
      // and add the current value to it
      acc[key] = [acc[key], val];
    }
 } else {
  // plain assignment if no special case is present
  acc[key] = val;
 }

return acc;
}, {});

const params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5&def=dude');
const output = groupParamsByKey(params) // {abc: "foo", def: ["[asf]", "dude"], xyz: 5}

这是一个简单的版本,显然你需要添加一些错误检查:

var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
    var split = pairs[i].split('=');
    obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}