背景
有这样子一个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 aboveencodeURIComponent(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 existsif (queryString.indexOf('?') === 0) {queryString = queryString.substr(1);}if (!queryString.length) {return dictionary;}// Step 1: separate out each key/value pairconst parts = queryString.split('&');for (let i = 0; i < parts.length; i++) {const p = parts[i];// Step 2: Split Key/Value pairconst keyValuePair = p.split('=');// Step 3: Add Key/Value pair to Dictionary objectconst key = keyValuePair[0];let value = keyValuePair[1];// decode URI encoded stringvalue && value.replace(/\+/g, '%20');value = decodeURIComponent(value); // 解码dictionary[key] = value;}// Step 4: Return Dictionary Objectreturn dictionary;
}