我有一个这样的字符串:

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

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

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

当前回答

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}

其他回答

ES6一行(如果我们可以这样称呼它,看到长行)

[…新URLSearchParams (location.search) .entries())。Reduce ((prev, [key,val]) => {prev[key] = val;返回prev}, {})

有一个名为YouAreI.js的轻量级库,它经过测试,使这个非常简单。

YouAreI = require('YouAreI')
uri = new YouAreI('http://user:pass@www.example.com:3000/a/b/c?d=dad&e=1&f=12.3#fragment');

uri.query_get() => { d: 'dad', e: '1', f: '12.3' }

下面是我的快速而粗糙的版本,基本上它将以'&'分隔的URL参数拆分为数组元素,然后迭代该数组,将以'='分隔的键/值对添加到一个对象中。我使用decodeURIComponent()将编码字符转换为正常的字符串等效(因此%20变成空格,%26变成'&'等):

function deparam(paramStr) {
    let paramArr = paramStr.split('&');     
    let paramObj = {};
    paramArr.forEach(e=>{
        let param = e.split('=');
        paramObj[param[0]] = decodeURIComponent(param[1]);
    });
    return paramObj;
}

例子:

deparam('abc=foo&def=%5Basf%5D&xyz=5')

返回

{
    abc: "foo"
    def:"[asf]"
    xyz :"5"
}

唯一的问题是xyz是一个字符串而不是一个数字(由于使用decodeURIComponent()),但除此之外,它不是一个坏的起点。

/** * 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

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

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