如何将URL参数转换为JavaScript对象?在2021年...请认为这已过时。编辑原始答案

我有一个这样的字符串:

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

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

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

答案 1

在2021年...请认为这已过时。

编辑

此编辑根据注释改进并解释了答案。

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=[asf]&xyz=5
  • 转义引号:相同,因为没有引号
  • 替换 &:abc=foo","def=[asf]","xyz=5
  • 替换 =:abc":"foo","def":"[asf]","xyz":"5
  • 四轮与卷曲和报价:{"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,"\":\"")) + '"}')

答案 2

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,替换为 .paramsToObjectObject.fromEntries(entries)

要迭代的值对是列表名称-值对,其中键是名称,值是值。

由于 返回一个可迭代对象,因此使用 spread 运算符而不是调用也会根据其规范生成条目: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}