解析复杂URL【面试题】

Question

输入:

例如:url = https://www.youzan.com?name=coder&age=20&callback=https%3A%2F%2Fyouzan.com%3Fname%3Dtest&list[]=a&json=%7B%22str%22%3A%22abc%22,%22num%22%3A123%7D

输出:

{
    
    
  name: "coder",
  age: "20",
  callback: "https://youzan.com?name=test", 
  list: ["a"],
  json: {
    
    
      str: 'abc',
      num: 123
   }
}

key factors analysis【看似容易,还是遇到几个坑】

1. url中部分特殊符号乱码,需要进行解码处理。

这里用到JavaScript自带的decodeURIComponent(url)方法进行解码,也可以自写decode函数。

[’%3A’ => ‘:’], [’%2F%2F’ => ‘//’] [’%3F’ => ‘?’] [’%3D’ => ‘=’]

//url = https://www.youzan.com?name=coder&age=20&callback=https%3A%2F%2Fyouzan.com%3Fname%3Dtest&list[]=a&json=%7B%22str%22%3A%22abc%22,%22num%22%3A123%7D
url = decodeURIComponent(url);
//url = https://www.youzan.com?name=coder&age=20&callback=https://youzan.com?name=test&list[]=a&json={"str":"abc","num":123}

2. 不能用常规的‘?’分离出参数部分

因为callback=https://youzan.com ? name=test 也包含问号,会导致分割出错。那么更合理的分割方式是直接用每个参数连接符号‘&’分割每个参数。

let paramArrays = url.split('&');

3. 处理第一项参数的多余前缀。

第一个参数项前半部分是访问地址,需要去掉。

注意,方法一有问题,当把callback参数放在第一个参数的位置,会出现name=test。方法二是改进方法。

// 方法一
paramArrays[0]= paramArrays[0].split('?')[1];
// 方法二
paramArrays[0] = paramArrays[0].split('?');
paramArrays[0].shift();
paramArrays[0] = paramArrays[0].join('?');

4. 把每个参数项目分割出键值对注意等号=特殊情况

如:callback=https://youzan.com?name = test 参数的value中也携带了=时候,用方法一也导致value的第一个=后面内容丢失,改进方法二。

// 方法一
let itemArray = item.split('=');
let key = itemArray[0], value = itemArray[1]; //丢失'test'
// 方法二
let itemArray = item.split('=');
let key = itemArray.shift(), value = itemArray.join('='); // 注意多个等号切割问题

Answer

const testURL = 'https://www.youzan.com?name=coder&callback=https%3A%2F%2Fyouzan.com%3Fname%3Dtest&age=20&callback=https%3A%2F%2Fyouzan.com%3Fname%3Dtest&list[]=a&json=%7B%22str%22%3A%22abc%22,%22num%22%3A123%7D';
function parseQuery(url) {
    
    
    let decodeUrl = decodeURIComponent(url);
    let obj = {
    
    };
    let paramArrays = decodeUrl.split('&');
    paramArrays[0] = paramArrays[0].split('?');
    paramArrays[0].shift();
    paramArrays[0] = paramArrays[0].join('?');

    paramArrays.map((item) => {
    
    
        let itemArray = item.split('=');
        let key = itemArray.shift(), value = itemArray.join('='); // 注意多个等号切割问题
        // 处理数组list[]=a 特殊情况
        if(key.indexOf('[') + 1 === key.indexOf(']')) {
    
    
            key = key.slice(0, key.length-2);
            value = [].concat(value);
        }
        obj[key] = value;
    })
    return obj;
}
parseQuery(testURL)

「以上纯属个人解答,欢迎指出不足之处」

猜你喜欢

转载自blog.csdn.net/m0_38073011/article/details/112320785