我有一个像这样的字符串:
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,"\":\"")) + '"}')
JSON.parse('{"' + decodeURI(location.search.substring(1).replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
,该代码将解析从URL查询参数中检索到的字符串,并将其转换为JavaScript对象。 - Daniël Tulp从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
返回一个 可迭代对象,使用 spread operator 而不是调用 .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://dev59.com/aXI-5IYBdhLWcg3wpqIK#1746566,没有规范来决定如何处理它,每个框架的行为可能不同。
常见的用例是将两个相同的值合并为一个数组,使输出对象变为:
{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}
let temp={};Object.keys(params).map(key=>{temp[key]=urlParams.getAll(key)})
- Tirumaleshwar Keregaddefoo[]: [1, 2, 3]
的形式出现,但我想要的是 foo: [1, 2, 3]
,所以我添加了一行额外的代码:const [ _key, val ] = tuple
const key = _key.replace(/\[]$/, '')
- Emeke Ajeh一句话概括,干净简洁。
const params = Object.fromEntries(new URLSearchParams(location.search));
针对您的具体情况,应该是:
const str = 'abc=foo&def=%5Basf%5D&xyz=5';
const params = Object.fromEntries(new URLSearchParams(str));
console.log(params);
?someValue=false
会变成 { someValue: "false" }
。 - Simon?foo=bar1&foo=bar2
的操作,我们只会得到 { foo: 'bar2' }
。
Node.js 请求对象将其解析为 { foo: ['bar1', 'bar2'] }
。 - Siipe2023一行代码方法
对于一般情况,您想将查询参数解析为对象:
Object.fromEntries(new URLSearchParams(location.search));
对于您的具体情况:
Object.fromEntries(new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5'));
[...new URLSearchParams(window.location.search)].reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
。 - dman?booleanValue=true
转换为 { booleanValue: "true" }
,这可能是不希望的。 - Chris Hayes将字符串使用 &
进行分割,得到键值对,然后针对每个键值对再使用 =
进行分割。以下是一个示例:
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);
});
目前我找到的解决方案并不涵盖更复杂的情况。
我需要将像以下这样的查询字符串:
https://random.url.com?Target=Offer&Method=findAll&filters%5Bhas_goals_enabled%5D%5BTRUE%5D=1&filters%5Bstatus%5D=active&fields%5B%5D=id&fields%5B%5D=name&fields%5B%5D=default_goal_name
转换为如下对象:
{
"Target": "Offer",
"Method": "findAll",
"fields": [
"id",
"name",
"default_goal_name"
],
"filters": {
"has_goals_enabled": {
"TRUE": "1"
},
"status": "active"
}
}
或者:
https://random.url.com?Target=Report&Method=getStats&fields%5B%5D=Offer.name&fields%5B%5D=Advertiser.company&fields%5B%5D=Stat.clicks&fields%5B%5D=Stat.conversions&fields%5B%5D=Stat.cpa&fields%5B%5D=Stat.payout&fields%5B%5D=Stat.date&fields%5B%5D=Stat.offer_id&fields%5B%5D=Affiliate.company&groups%5B%5D=Stat.offer_id&groups%5B%5D=Stat.date&filters%5BStat.affiliate_id%5D%5Bconditional%5D=EQUAL_TO&filters%5BStat.affiliate_id%5D%5Bvalues%5D=1831&limit=9999
转化为:
{
"Target": "Report",
"Method": "getStats",
"fields": [
"Offer.name",
"Advertiser.company",
"Stat.clicks",
"Stat.conversions",
"Stat.cpa",
"Stat.payout",
"Stat.date",
"Stat.offer_id",
"Affiliate.company"
],
"groups": [
"Stat.offer_id",
"Stat.date"
],
"limit": "9999",
"filters": {
"Stat.affiliate_id": {
"conditional": "EQUAL_TO",
"values": "1831"
}
}
}
代码:
var getParamsAsObject = function (query) {
query = query.substring(query.indexOf('?') + 1);
var re = /([^&=]+)=?([^&]*)/g;
var decodeRE = /\+/g;
var decode = function (str) {
return decodeURIComponent(str.replace(decodeRE, " "));
};
var params = {}, e;
while (e = re.exec(query)) {
var k = decode(e[1]), v = decode(e[2]);
if (k.substring(k.length - 2) === '[]') {
k = k.substring(0, k.length - 2);
(params[k] || (params[k] = [])).push(v);
}
else params[k] = v;
}
var assign = function (obj, keyPath, value) {
var lastKeyIndex = keyPath.length - 1;
for (var i = 0; i < lastKeyIndex; ++i) {
var key = keyPath[i];
if (!(key in obj))
obj[key] = {}
obj = obj[key];
}
obj[keyPath[lastKeyIndex]] = value;
}
for (var prop in params) {
var structure = prop.split('[');
if (structure.length > 1) {
var levels = [];
structure.forEach(function (item, i) {
var key = item.replace(/[?[\]\\ ]/g, '');
levels.push(key);
});
assign(params, levels, params[prop]);
delete(params[prop]);
}
}
return params;
};
obj=encodeURIComponent(JSON.stringify({what:{ever:','},i:['like']}))
。 - chickenslocation.search
.slice(1)
.split('&')
.map(p => p.split('='))
.reduce((obj, pair) => {
const [key, value] = pair.map(decodeURIComponent);
obj[key] = value;
return obj;
}, {});
这是简化版,显然你需要添加一些错误检查:
var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
var split = pairs[i].split('=');
obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}
JSON.parse('{"' + decodeURIComponent(query.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'));
对我有效。 - Danil Gaponovname[]=test1&name[]=test2
,并且会导致 name[]=test2
的结果。 - Rafeesplit[1]
替换为split.slice(1).join("=")
。 - tigrou对于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
我发现$.String.deparam是最完整的预构建解决方案(可以处理嵌套对象等)。请查看文档。