【js】URL处理
背景
有这样子一个url,search部分的value可能包含空格,也可能是一个对象,如何正确解析这样子的url呢?
search如下,?accountId=144115188076933939&accountName=mock name&xxx
{
"accountId": "144115188076933939",
"accountName": "mock name", // 空格
"accountNumber": "*1623",
"accountType": "6",
"bankId": "36",
"bankName": "DUIT NOW OB PHONE NUMBER",
"proxyType": "1",
"recipientType": "3",
"saved": "true",
"status": "2",
"test": { // json对象
"1": 1,
"2": 2
}
}
空格
通常来说,空格在URL中通常需要被编码为%20或者+。有这样子的两个方法,encodeURIComponent和decodeURIComponent对url进行编码和解码操作。
encodeURIComponent('?accountId=144115188076933939&accountName=mock name')
// 输出
?accountId=144115188076933939&accountName=mock%20name
json对象
编码的时候,将对象序列化成字符串,然后再调用encodeURIComponent;
解码的时候,就先parse成对象,再调用decodeURIComponent。
代码
遍历json对象,如果value为对象的话,则将其stringify成字符串:
export function shallowStringifyObjectFields(
obj: Record<
string,
string | number | boolean | Record<string, unknown> | null | undefined
>
): Record<string, string | number | boolean | null | undefined> {
const newObj: Record<
string,
string | number | boolean | null | undefined
> = {};
for (const key of Object.keys(obj)) {
const val = obj[key];
if (typeof val === 'object' && val) {
newObj[key] = JSON.stringify(val);
} else {
newObj[key] = val;
}
}
return newObj;
}
将对象转换成url search,类似?xx=xx这样子的字符串:
/**
* format a javascript object into query string, keep the key value in alphabetic order
* @static
* @param {object} json
* @returns {string} query string
*/
export function jsonToQueryString(
json: Record<
string,
string | null | undefined | number | boolean | Array<any>
>,
skipQuestionMark = false
): string {
if (!json) {
return '';
}
const keys = Object.keys(json).filter(key => {
const val = json[key];
return typeof val !== 'undefined' && val !== null;
});
if (!keys.length) {
return '';
}
return (
(skipQuestionMark ? '' : '?') +
keys
.sort()
.map(function (key) {
return (
encodeURIComponent(key) +
'=' +
// undefined | null is already filtered out above
encodeURIComponent(json[key] as string | number | boolean)
);
})
.join('&')
);
}
将url search字符串解析成对象:
/**
* Parse query string using string splitting
* @static
* @param {string} queryString
* @return {Object.<string>}
*/
export function parseQueryStringToObj(
queryString: string | null | undefined
): {
[key: string]: string;
} {
const dictionary: {
[key: string]: string;
} = {};
if (typeof queryString !== 'string' || queryString.length === 0) {
return dictionary;
}
// remove the '?' from the beginning of the
// if it exists
if (queryString.indexOf('?') === 0) {
queryString = queryString.substr(1);
}
if (!queryString.length) {
return dictionary;
}
// Step 1: separate out each key/value pair
const parts = queryString.split('&');
for (let i = 0; i < parts.length; i++) {
const p = parts[i];
// Step 2: Split Key/Value pair
const keyValuePair = p.split('=');
// Step 3: Add Key/Value pair to Dictionary object
const key = keyValuePair[0];
let value = keyValuePair[1];
// decode URI encoded string
value && value.replace(/\+/g, '%20');
value = decodeURIComponent(value); // 解码
dictionary[key] = value;
}
// Step 4: Return Dictionary Object
return dictionary;
}