我有一个这样的字符串:
abc=foo&def=%5Basf%5D&xyz=5
如何将其转换为这样的 JavaScript 对象?
{
abc: 'foo',
def: '[asf]',
xyz: 5
}
我有一个这样的字符串:
abc=foo&def=%5Basf%5D&xyz=5
如何将其转换为这样的 JavaScript 对象?
{
abc: 'foo',
def: '[asf]',
xyz: 5
}
此编辑根据评论改进并解释了答案。
var search = location.search.substring(1);
JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')
例子
分abc=foo&def=%5Basf%5D&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,"\":\"")) + '"}')
从 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,替换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}
ES6 一个内胆。干净简单。
Object.fromEntries(new URLSearchParams(location.search));
对于您的具体情况,它将是:
let str = 'abc=foo&def=%5Basf%5D&xyz=5';
let obj = Object.fromEntries(new URLSearchParams(str));
console.log(obj);
对于要将查询参数解析为对象的一般情况:
Object.fromEntries(new URLSearchParams(location.search));
对于您的具体情况:
Object.fromEntries(new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5'));
如果您无法使用Object.fromEntries
,这也将起作用:
Array.from(new URLSearchParams(window.location.search)).reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
正如 dman 所建议的,如果您也无法使用Array.from
,这将起作用:
[...new URLSearchParams(window.location.search)].reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
拆分&
以获得名称/值对,然后拆分每个对=
。下面是一个例子:
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);
});
这是改编自 John Resig 的“Search and Don't Replace”。