给定一个对象{a:1,b:2,c:[1,2]}
输出一个查询字符串 ?a=1&b=2&c=1,2
const querystring = require('querystring');
function customStringify(obj) {
const parts = [];
for (const key in obj) {
if (Array.isArray(obj[key])) {
parts.push(`${key}=${obj[key].join(',')}`);
} else {
parts.push(`${key}=${obj[key]}`);
}
}
return `?${parts.join('&')}`;
}
const obj = { a: 1, b: 2, c: [1, 2] };
const queryString = customStringify(obj);
console.log(queryString); // ?a=1&b=2&c=1,2
实现一个 queryString 解析器,能够将输入的查询字符串解析为键值对,并以适当的数据结构返回。可能包括以下详细要求:
实现一个 parse 函数,接受查询字符串并将其转换为键值对的对象(或字典、映射等)。 确保解析器可以正确处理重复的键,将它们的值作为数组存储。 处理URL编码的字符,例如 %20 代表空格。 考虑边缘情况,例如空键、无值的键,以及查询字符串的多种分隔符。
function parseQueryString(queryString) {
// 移除开头的 '?',如果有的话
if (queryString.startsWith('?')) {
queryString = queryString.slice(1);
//第一个参数(start)表示子串的起始位置(包含)。
//第二个参数(end,可选)表示子串的结束位置(不包含)。
}
// 使用 '&' 分隔不同的键值对
const pairs = queryString.split('&');
// let text = "apple,banana,orange";
// let result = text.split(",");
// // 输出:["apple", "banana", "orange"]
// 初始化一个对象存储解析结果
const parsed = {};
pairs.forEach((pair) => {
if (pair) {
// 使用 '=' 分隔键和值
//const pair = "name=John%20Doe";
// const result = pair.split('=', 2);
// result: ["name", "John%20Doe"]
const [key, value = ''] = pair.split('=', 2).map(decodeURIComponent);
//map 是数组的方法,用于对数组中的每个元素应用一个函数并返回一个新的数组。 decodeURIComponent 是 JavaScript 内置的函数,用于解码 URL 编码字符。
if (key) {
// 将重复的键值作为数组存储
if (key in parsed) {
//Array.isArray(parsed[key]) 检查这个值是否是一个数组。
if (Array.isArray(parsed[key])) {
//push 将新值 value 添加到这个数组中
parsed[key].push(value);
} else {
//如果是数组,则使用 push 将新值 value 添加到数组中。
// 否则,将单一值转换为数组,并添加新值 value。
parsed[key] = [parsed[key], value];
}
} else {
//如果 key 不存在于 parsed 对象中,将 key 和 value 直接添加到 parsed 中。
parsed[key] = value;
}
}
}
});
return parsed;
}
// 示例使用
const queryString = "name=John%20Doe&age=25&name=Jane%20Doe&empty=&no_value";
const parsedResult = parseQueryString(queryString);
console.log(parsedResult);
RESULT
{
name: ['John Doe', 'Jane Doe'],
age: '25',
empty: '',
no_value: ''
}