我有一个这样的字符串:
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 params = {};
window.location.search.substring(1).split('&').forEach(function(pair) {
pair = pair.split('=');
if (pair[1] !== undefined) {
var key = decodeURIComponent(pair[0]),
val = decodeURIComponent(pair[1]),
val = val ? val.replace(/\++/g,' ').trim() : '';
if (key.length === 0) {
return;
}
if (params[key] === undefined) {
params[key] = val;
}
else {
if ("function" !== typeof params[key].push) {
params[key] = [params[key]];
}
params[key].push(val);
}
}
});
console.log(params);
基本用法。 ? = aa&b = bb 对象{a: "aa", b: "bb"}
重复参数,例如。 ? = aa&b = bb&c = cc&c =土豆 对象{a: "aa", b: "bb", c: ["cc","potato"]}
钥匙不见了。 ? = aa&b = bb = cc 对象{a: "aa", b: "bb"}
缺少值,例如。 = aa&b = bb&c ? 对象{a: "aa", b: "bb"}
上述JSON/regex解决方案在这个古怪的url上抛出了一个语法错误: ? = aa&b = bb&c = & = dd&e 对象{a: "aa", b: "bb", c: ""}
其他回答
另一种基于URLSearchParams最新标准的解决方案(https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
function getQueryParamsObject() {
const searchParams = new URLSearchParams(location.search.slice(1));
return searchParams
? _.fromPairs(Array.from(searchParams.entries()))
: {};
}
请注意,这个解决方案是利用
Array.from (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
和lodash的_. fropairs (https://lodash.com/docs#fromPairs),以便简单。
因为您可以访问searchParams.entries()迭代器,所以创建一个更兼容的解决方案应该很容易。
对于Node JS,你可以使用Node JS API querystring:
const querystring = require('querystring');
querystring.parse('abc=foo&def=%5Basf%5D&xyz=5&foo=b%3Dar');
// returns the object
文档:https://nodejs.org/api/querystring.html
下面是我用的一个例子:
var params = {};
window.location.search.substring(1).split('&').forEach(function(pair) {
pair = pair.split('=');
if (pair[1] !== undefined) {
var key = decodeURIComponent(pair[0]),
val = decodeURIComponent(pair[1]),
val = val ? val.replace(/\++/g,' ').trim() : '';
if (key.length === 0) {
return;
}
if (params[key] === undefined) {
params[key] = val;
}
else {
if ("function" !== typeof params[key].push) {
params[key] = [params[key]];
}
params[key].push(val);
}
}
});
console.log(params);
基本用法。 ? = aa&b = bb 对象{a: "aa", b: "bb"}
重复参数,例如。 ? = aa&b = bb&c = cc&c =土豆 对象{a: "aa", b: "bb", c: ["cc","potato"]}
钥匙不见了。 ? = aa&b = bb = cc 对象{a: "aa", b: "bb"}
缺少值,例如。 = aa&b = bb&c ? 对象{a: "aa", b: "bb"}
上述JSON/regex解决方案在这个古怪的url上抛出了一个语法错误: ? = aa&b = bb&c = & = dd&e 对象{a: "aa", b: "bb", c: ""}
如果你正在使用URI.js,你可以使用:
https://medialize.github.io/URI.js/docs.html#static-parseQuery
var result = URI.parseQuery("?foo=bar&hello=world&hello=mars&bam=&yup");
result === {
foo: "bar",
hello: ["world", "mars"],
bam: "",
yup: null
};
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}