我有一个这样的字符串:
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
}
当前回答
我也遇到了同样的问题,尝试了这里的解决方案,但没有一个真正有效,因为我在URL参数中有数组,像这样:
?param[]=5¶m[]=8&othr_param=abc¶m[]=string
所以我最终写了我自己的JS函数,它使一个数组的参数在URI:
/**
* Creates an object from URL encoded data
*/
var createObjFromURI = function() {
var uri = decodeURI(location.search.substr(1));
var chunks = uri.split('&');
var params = Object();
for (var i=0; i < chunks.length ; i++) {
var chunk = chunks[i].split('=');
if(chunk[0].search("\\[\\]") !== -1) {
if( typeof params[chunk[0]] === 'undefined' ) {
params[chunk[0]] = [chunk[1]];
} else {
params[chunk[0]].push(chunk[1]);
}
} else {
params[chunk[0]] = chunk[1];
}
}
return params;
}
其他回答
下面是硅制品方法的一个更简化的版本。
下面的函数可以从USVString或Location解析查询字符串。
/** * Returns a plain object representation of a URLSearchParams object. * @param {USVString} search - A URL querystring * @return {Object} a key-value pair object from a URL querystring */ const parseSearch = (search) => [...new URLSearchParams(search).entries()] .reduce((acc, [key, val]) => ({ ...acc, // eslint-disable-next-line no-nested-ternary [key]: Object.prototype.hasOwnProperty.call(acc, key) ? Array.isArray(acc[key]) ? [...acc[key], val] : [acc[key], val] : val }), {}); /** * Returns a plain object representation of a URLSearchParams object. * @param {Location} location - Either a document or window location, or React useLocation() * @return {Object} a key-value pair object from a URL querystring */ const parseLocationSearch = (location) => parseSearch(location.search); console.log(parseSearch('?foo=bar&x=y&ids=%5B1%2C2%2C3%5D&ids=%5B4%2C5%2C6%5D')); .as-console-wrapper { top: 0; max-height: 100% !important; }
下面是上面代码的一行代码(125字节):
f是parsearchch
f=s=>[...new URLSearchParams(s).entries()].reduce((a,[k,v])=>({...a,[k]:a[k]?Array.isArray(a[k])?[...a[k],v]:[a[k],v]:v}),{})
Edit
下面是一个序列化和更新的方法:
const parseSearch = (search) => [...new URLSearchParams(search).entries()] .reduce((acc, [key, val]) => ({ ...acc, // eslint-disable-next-line no-nested-ternary [key]: Object.prototype.hasOwnProperty.call(acc, key) ? Array.isArray(acc[key]) ? [...acc[key], val] : [acc[key], val] : val }), {}); const toQueryString = (params) => `?${Object.entries(params) .flatMap(([key, values]) => Array.isArray(values) ? values.map(value => [key, value]) : [[key, values]]) .map(pair => pair.map(val => encodeURIComponent(val)).join('=')) .join('&')}`; const updateQueryString = (search, update) => (parsed => toQueryString(update instanceof Function ? update(parsed) : { ...parsed, ...update })) (parseSearch(search)); const queryString = '?foo=bar&x=y&ids=%5B1%2C2%2C3%5D&ids=%5B4%2C5%2C6%5D'; const parsedQuery = parseSearch(queryString); console.log(parsedQuery); console.log(toQueryString(parsedQuery) === queryString); const updatedQuerySimple = updateQueryString(queryString, { foo: 'baz', x: 'z', }); console.log(updatedQuerySimple); console.log(parseSearch(updatedQuerySimple)); const updatedQuery = updateQueryString(updatedQuerySimple, parsed => ({ ...parsed, ids: [ ...parsed.ids, JSON.stringify([7,8,9]) ] })); console.log(updatedQuery); console.log(parseSearch(updatedQuery)); .as-console-wrapper { top: 0; max-height: 100% !important; }
ES6有一个非常简单而不正确的答案:
console.log(
Object.fromEntries(new URLSearchParams(`abc=foo&def=%5Basf%5D&xyz=5`))
);
但是这一行代码不包括多个相同的键,你必须使用更复杂的东西:
function parseParams(params) {
const output = [];
const searchParams = new URLSearchParams(params);
// Set will return only unique keys()
new Set([...searchParams.keys()])
.forEach(key => {
output[key] = searchParams.getAll(key).length > 1 ?
searchParams.getAll(key) : // get multiple values
searchParams.get(key); // get single value
});
return output;
}
console.log(
parseParams('abc=foo&cars=Ford&cars=BMW&cars=Skoda&cars=Mercedes')
)
代码将生成如下结构:
[
abc: "foo"
cars: ["Ford", "BMW", "Skoda", "Mercedes"]
]
我发现$. string .deparam是最完整的预构建解决方案(可以做嵌套对象等)。查看文档。
我还需要在URL的查询部分处理+ (decodeURIComponent没有),所以我改编了Wolfgang的代码成为:
var search = location.search.substring(1);
search = search?JSON.parse('{"' + search.replace(/\+/g, ' ').replace(/&/g, '","').replace(/=/g,'":"') + '"}',
function(key, value) { return key===""?value:decodeURIComponent(value)}):{};
在我的例子中,我使用jQuery来获得URL准备好的表单参数,然后这个技巧来构建一个对象,然后我可以轻松地更新对象上的参数并重新构建查询URL,例如:
var objForm = JSON.parse('{"' + $myForm.serialize().replace(/\+/g, ' ').replace(/&/g, '","').replace(/=/g,'":"') + '"}',
function(key, value) { return key===""?value:decodeURIComponent(value)});
objForm.anyParam += stringToAddToTheParam;
var serializedForm = $.param(objForm);
在2021年…请认为这是过时的。
Edit
这个编辑改进并解释了基于评论的答案。
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 = xyz (asf) = 5 转义引号:相同,因为没有引号 替换&:abc=foo","def=[asf]","xyz=5 " 5 . Replace =: abc":"foo","def":"[asf]","xyz": Suround卷曲和引用:{“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,"\":\"")) + '"}')