如何将 URL 参数转换为 JavaScript 对象?

新手上路,请多包涵

我有一个这样的字符串:

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

我怎样才能将它转换成这样的 JavaScript 对象?

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

原文由 Alex 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 957
2 个回答

在 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。

改进的解决方案 允许搜索字符串中包含更多字符。它使用 reviver 函数进行 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,"\":\"")) + '"}')

原文由 Wolfgang Kuehn 发布,翻译遵循 CC BY-SA 4.0 许可协议

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 和传播

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

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

由于 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}

原文由 silicakes 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题