我有一个这样的字符串:

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

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

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

当前回答

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

其他回答

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}
//under ES6 
const getUrlParamAsObject = (url = window.location.href) => {
    let searchParams = url.split('?')[1];
    const result = {};
    //in case the queryString is empty
    if (searchParams!==undefined) {
        const paramParts = searchParams.split('&');
        for(let part of paramParts) {
            let paramValuePair = part.split('=');
            //exclude the case when the param has no value
            if(paramValuePair.length===2) {
                result[paramValuePair[0]] = decodeURIComponent(paramValuePair[1]);
            }
        }

    }
    return result;
}

我发现$. string .deparam是最完整的预构建解决方案(可以做嵌套对象等)。查看文档。

在Mike Causer回答的基础上,我创建了这个函数,它考虑了具有相同键的多个参数(foo=bar&foo=baz)和逗号分隔的参数(foo=bar,baz,bin)。它还允许您搜索某个查询键。

function getQueryParams(queryKey) {
    var queryString = window.location.search;
    var query = {};
    var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
    for (var i = 0; i < pairs.length; i++) {
        var pair = pairs[i].split('=');
        var key = decodeURIComponent(pair[0]);
        var value = decodeURIComponent(pair[1] || '');
        // Se possui uma vírgula no valor, converter em um array
        value = (value.indexOf(',') === -1 ? value : value.split(','));

        // Se a key já existe, tratar ela como um array
        if (query[key]) {
            if (query[key].constructor === Array) {
                // Array.concat() faz merge se o valor inserido for um array
                query[key] = query[key].concat(value);
            } else {
                // Se não for um array, criar um array contendo o valor anterior e o novo valor
                query[key] = [query[key], value];
            }
        } else {
            query[key] = value;
        }
    }

    if (typeof queryKey === 'undefined') {
        return query;
    } else {
        return query[queryKey];
    }
}

示例输入: foo.html吗?博兹,foo = bar&foo = baz&foo =鹿角的第二叉,buz&bar = 1, 2, 3

示例输出

{
    foo: ["bar","baz","bez","boz","buz"],
    bar: ["1","2","3"]
}

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

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