解救URL参数困境:QS库教你如何变魔法师

前言

工作时候遇到想要把请求的参数添加到url中,以便别人通过携带参数的url地址直接访问并根据参数选好对应的选项。

自己去处理把参数通过js方法变化到一定格式添加到url地址中,再自己去一步步去解析还原到自己想要的数据结构。

这样对于简单的数据结构来说是轻易可以做到的,但是如果数据结构比较复杂的情况就比较复杂了

一:QS简介

QS库是一种用于处理URL查询字符串(Query String)的工具库,主要用于前端开发中。URL查询字符串是URL中问号后面的部分,通常包含各种参数和其对应的值。

二:导入QS

方式一:HTML中导入

可以使用在Web上托管的QS库的CDN链接。将以下代码添加到HTML文件中,即可使用CDN导入

js 复制代码
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.1/qs.js"></script>
js 复制代码
let qs = Qs
console.log(qs)

方式二:npm包

  1. a. 在终端中运行以下命令安装QS库:

    js 复制代码
    npm install qs

    b. 在你的JavaScript文件中导入QS库:

    js 复制代码
    // 例如,使用ES6模块的导入语法
    import qs from 'qs';

    或者,如果你使用CommonJS:

    js 复制代码
    const qs = require('qs');
    ```。

一旦你导入了QS库,你就可以在你的JavaScript代码中使用它来处理URL参数了。例如:

js 复制代码
const parsedParams = qs.parse(window.location.search, { ignoreQueryPrefix: true });
console.log(parsedParams);

上述代码将解析当前页面的URL查询字符串并将其作为JavaScript对象打印出来

三:使用

1.parse解析

使用 QS 库的 parse 方法可以将 URL 查询字符串解析为 JavaScript 对象。例如:

js 复制代码
const qs = require('qs');

const queryString = 'name=John&age=30&gender=male';
const parsedParams = qs.parse(queryString);

console.log(parsedParams);

输出

js 复制代码
{
  name: 'John',
  age: '30',
  gender: 'male'
}

2. stringify序列化

使用 QS 库的 stringify 方法可以将 JavaScript 对象序列化为 URL 查询字符串。例如:

js 复制代码
const qs = require('qs');

const params = {
  name: 'John',
  age: 30,
  gender: 'male'
};

const queryString = qs.stringify(params);

console.log(queryString);

输出

js 复制代码
name=John&age=30&gender=male

qs.stringify 方法默认使用 & 作为参数之间的分隔符,可以根据需要进行配置。

3. 配置项

  1. delimiter 指定用于分隔参数的字符串,默认为 '&'
js 复制代码
const queryString = 'name=John,age=30,gender=male';
const parsedParams = qs.parse(queryString, { delimiter: ',' });
  1. arrayFormat 控制序列化数组的方式,可选值有 'indices'(默认,通过添加索引来表示数组)、'brackets'(使用方括号表示数组)和'repeat'(重复参数名称表示数组)。
js 复制代码
const params = { colors: ['red', 'green', 'blue'] };
const queryString = qs.stringify(params, { arrayFormat: 'brackets' });
  1. encode 指定是否对参数进行URL编码,默认为 true
js 复制代码
const params = { name: 'John Doe' };
const queryString = qs.stringify(params, { encode: false });
  1. decode 指定是否对解析后的参数进行URL解码,默认为 true
js 复制代码
const queryString = 'name=John%20Doe';
const parsedParams = qs.parse(queryString, { decode: false });
  1. allowDots 指定是否允许在参数名称中使用点号.,默认为 false。如果设置为 true,则可以处理嵌套的对象。
js 复制代码
const params = { user: { name: 'John', age: 30 } };
const queryString = qs.stringify(params, { allowDots: true });
  1. ignoreQueryPrefix 指定是否忽略查询字符串的前缀(通常是 ?),默认为 false
js 复制代码
const queryString = '?name=John&age=30';
const parsedParams = qs.parse(queryString, { ignoreQueryPrefix: true });

四:具体场景

提出需求(万恶源头)...

某个查询界面,把查询请求参数,添加到url地址中,但是这个参数很多也很复杂,包括各种select框等等。

别人可以根据url地址中的参数,跳转到对应页面并且根据参数直接把select,input等相关选项选好

对于不选的选项,为空值,但是要保证url地址的美观...

序列化过程...

在某个查询界面,查询参数比较多,数据结构是嵌套的使用,有的选项也不必选就默认值为null,select不选数组就是空值。

对于这些空值就需要对这个数据结构过滤处理,这样添加到url太过冗余了。

原始数据类型,空数组,空对象就不需要被序列化。

举例

js 复制代码
  let qs = Qs
  const complexDataStructure = {
    name: 'John Doe',
    age: 30,
    address: {
      street: '123 Main St',
      city: 'Anytown',
      country: 'USA',
      tags: []
    },
    isStudent: false,
    grades: [90, 85, 92],
    metadata: {
      preferences: {
        theme: 'dark',
        fontSize: 16
      }
    },
    emptyArray: [],
    emptyObject: {},
    nullableValue: null
  }

  console.log(qs.stringify(complexDataStructure))

name=John%20Doe&age=30&address%5Bstreet%5D=123%20Main%20St&address%5Bcity%5D=Anytown&address%5Bcountry%5D=USA&isStudent=false&grades%5B0%5D=90&grades%5B1%5D=85&grades%5B2%5D=92&metadata%5Bpreferences%5D%5Btheme%5D=dark&metadata%5Bpreferences%5D%5BfontSize%5D=16&nullableValue=

太过冗余了,需要过滤一下

过滤空值...

过滤函数

js 复制代码
const filterValues = function (obj) {
const filteredObj = {}
for (const key in obj) {
  const value = obj[key]

  if (Array.isArray(value)) {
    // 处理数组
    if (value.length > 0) {
      filteredObj[key] = value
    }
  } else if (value !== null && value !== '') {
    if (typeof value === 'object') {
      // 递归处理嵌套对象
      const nestedFiltered = filterValues(value)
      if (Object.keys(nestedFiltered).length > 0) {
        filteredObj[key] = nestedFiltered
      }
    } else {
      filteredObj[key] = value
    }
  }
}
return filteredObj
}

// 获取过滤后的数据
const filteredData = filterValues(complexDataStructure)
console.log(filteredData)

把空值和空数组过滤掉了,这下再序列化就不会那么冗余了

js 复制代码
{
    "name": "John Doe",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "country": "USA"
    },
    "isStudent": false,
    "grades": [
        90,
        85,
        92
    ],
    "metadata": {
        "preferences": {
            "theme": "dark",
            "fontSize": 16
        }
    }
}
    
    

一般把这个函数添加到请求前面即可...

序列化 + 拼接url

js 复制代码
const queryString = qs.stringify(filteredData)

let url = new URL(window.location.href)
const baseUrl = url.origin + url.pathname
const fullUrl = baseUrl + '?' + queryString
window.history.replaceState({}, '', fullUrl);

//
http://127.0.0.1:5500/qs.html?name=John%20Doe&age=30&address%5Bstreet%5D=123%20Main%20St&address%5Bcity%5D=Anytown&address%5Bcountry%5D=USA&isStudent=false&grades%5B0%5D=90&grades%5B1%5D=85&grades%5B2%5D=92&metadata%5Bpreferences%5D%5Btheme%5D=dark&metadata%5Bpreferences%5D%5BfontSize%5D=16

模拟用户重新选择选项,修改数据

js 复制代码
complexDataStructure.age = 50
complexDataStructure.nullableValue = true
complexDataStructure.grades = [0, 0, 0]
complexDataStructure.metadata.preferences.theme = '0'

这里用户修改完数据后,重新打请求url地址参数也就会再次变化

解析 + 还原...

由于需求是别人通过你的url中的参数,可以直接选择好对应的选项并查询。

但是由于还要考虑url参数美观,我们过滤掉了空数组,空对象等。

那么对于select组件就一定会报错,空数组没有length长度等问题。

因此我们还要把原先的空值再给他还原回去...但如果创建新对象去处理就比较复杂了

直接跟原先数据结构进行对比,没有的字段直接用原先的就好了

解析 + 比对

js 复制代码
const currentUrl = window.location.href
const params = currentUrl.split('?')[1]
const parsedData = qs.parse(params)
if (params) {
try {
  for (const key in parsedData) {
    if (parsedData.hasOwnProperty(key)) {
      // 如果解析出来的值不为 null 或空字符串,更新 complexDataStructure
      if (parsedData[key] !== null && parsedData[key] !== '') {
        complexDataStructure[key] = parsedData[key]
      }
    }
  }
} catch (error) {
  console.error('Error parsing JSON:', error)
}
}

console.log(complexDataStructure) 

这个过程就是把修改的数据再填到原先的数据结构complexDataStructure中,这样子空值咱们就完全不用管了

js 复制代码
{
    "name": "John Doe",
    "age": "50",
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "country": "USA"
    },
    "isStudent": "false",
    "grades": [
        "0",
        "0",
        "0"
    ],
    "metadata": {
        "preferences": {
            "theme": "0",
            "fontSize": "16"
        }
    },
    "emptyArray": [],
    "emptyObject": {},
    "nullableValue": "true"
}

这样子用户根据url参数跳转过去,直接就根据参数选好了,url参数也过滤了,属于是非常美观了...

那么结果也就very biu特佛了...

相关推荐
HEX9CF13 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
凌云行者25 分钟前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻42 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江43 分钟前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
Z3r4y44 分钟前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
___Dream44 分钟前
【黑马软件测试三】web功能测试、抓包
前端·功能测试
金灰44 分钟前
CSS3练习--电商web
前端·css·css3
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
Tandy12356_1 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
TonyH20021 小时前
webpack 4 的 30 个步骤构建 react 开发环境
前端·css·react.js·webpack·postcss·打包