常用ASCII URL编码对照表,JavaScript中如何把url的%20、%22、%28、%29、%7B、%7D解析还原成真实的字符

【问题描述】:

笔者遇到过这样一个需求,在http的拦截器中拦截url并添加一些额外的参数,代码如下:

// http request 拦截器
// instance: axios实例
this.instance.interceptors.request.use(
  config => {
    const authParams: any = LocalStorage.get(STORAGE_KEY.IFRAME_PARAMS)
   // 替换url,替换参数
      const {url, baseURL, params} = config
      let [pathname, search] = url.split('?')
      const temp = search ? this.parseParams(search) : {}
      Object.assign(temp, authParams)          // 覆盖原请求中的部分参数
      const newParams = this.getQueryString(temp)
      config.url = newParams ? `${pathname}?${newParams}` : pathname        // 使用?拼接成新的url
    return config
  },
  err => {
    return Promise.reject(err)
  })
  
/**
   * @desc 解析跳转进来的路由参数,为对象
   * '?type=1&iframe=true'
   * =>
   * {type: "1"
      iframe: "true"
      }
   */
  parseParams(search) {
    const ret = {},
     seg = search.replace(/^\?/, '').split('&'),
     len = seg.length
    let i = 0, s
    for (; i < len; i++) {
      if (!seg[i]) {
        continue
      }
      s = seg[i].split('=')
      ret[s[0]] = s[1]
    }
    return ret
  }

比如拦截http请求(1):
https://xxx.com/report/list?title=customer_number&endTime=2020-06-30%2023:59:59&startTime=2020-06-01%2000:00:00&pageSize=20&currentPageNo=1
添加参数后变成请求(2):
https://xxx.com/report/list?timestamp=1595314770&sign=9bc3fd371169e2b4fb6184ed081b0817&currentPageNo=1&pageSize=20&startTime=2020-06-01%252000:00:00&endTime=2020-06-30%252023:59:59&title=customer_number
对比可知添加了参数:

// B
{
  timestamp: 1595314770,
  sign:9bc3fd371169e2b4fb6184ed081b0817
}

我的做法是解析成元url中?后面的参数成object(A),然后把新的参数(B)拼接到A上,再更新新的url的参数,看似逻辑木得问题,但是!发请求的时候就是失败,并且报错:参数[startTime]格式错误,咦,笔者都没有操作startTime啊,怎么会参数错误呢?

【错因查找】:

笔者瞪大着高度近视的小眼睛,观察了半天才发现,原来两个url中的startTime参数真的不一样,
请求(1)中startTime:startTime=2020-06-01%2000:00:00
请求(2)中startTime:startTime=2020-06-01%252000:00:00
额,笔者当时上传的参数未:startTime=2020-06-01 00:00:00,明明是空格(space),肿么变成了%20,又变成了%25呢?原来是特殊字符的锅。。。

由于url支持26个英文字母、数字和少数几个特殊字符,因此,对于url中包含非标准url的字符时,就需要对其进行编码。
较为特殊的字符例如:@&=+$,/?%!*’();:#[]

当客户端发请求时,浏览器会自动对含有这些字符的部分进行处理,根据👇的HTML URL 编码表可以发现,笔者参数中的空格()被转义成了%20,在拦截器中拦截请求时,%又是特殊字符,被转义成了%25,因此请求(2)的startTime会变成2020-06-01%252000:00:00,既然bug找到了,下面就是解决bug啦ღღღღღღ

【解决方法】:

既然请求(1)中2020-06-01 00:00:00被转义成了2020-06-01%2000:00:00,那么我们把2020-06-01%2000:00:00反转义成真实的字符,那么请求(2)中再转义一次也还是正确的,就不会报错啦❀

因此笔者优化了👆的parseParams(),如下,第二行中的decodeURIComponent(search)可以对对编码后的search进行解码,将诸如%20这样的字符解码成特殊字符空格(

parseParams(search) {
    const ret = {}, seg = decodeURIComponent(search).replace(/^\?/, '').split('&'), len = seg.length
    let i = 0, s
    for (; i < len; i++) {
      if (!seg[i]) {
        continue
      }
      s = seg[i].split('=')
      ret[s[0]] = s[1]
    }
    return ret
  }
【重点知识】:
  1. JavaScript decodeURIComponent() 函数:用于解码由 encodeURIComponent 方法或者其它类似方法编码的部分统一资源标识符(URI)。

点击F12(或者Fn + F12)打开控制台,输入如下指令:

console.log(decodeURIComponent("%2b"))

把%2b替换为你想查询的16进制(+)即可。

【附录】:

URL 编码 - 从 %00 到 %8f

ASCII ValueURL-encodeASCII ValueURL-encodeASCII ValueURL-encode
æ%000%30`%60
 %011%31a%61
 %022%32b%62
 %033%33c%63
 %044%34d%64
 %055%35e%65
 %066%36f%66
 %077%37g%67
backspace%088%38h%68
tab%099%39i%69
linefeed%0a:%3aj%6a
 %0b;%3bk%6b
 %0c<%3cl%6c
c return%0d=%3dm%6d
 %0e>%3en%6e
 %0f?%3fo%6f
 %10@%40p%70
 %11A%41q%71
 %12B%42r%72
 %13C%43s%73
 %14D%44t%74
 %15E%45u%75
 %16F%46v%76
 %17G%47w%77
 %18H%48x%78
 %19I%49y%79
 %1aJ%4az%7a
 %1bK%4b{%7b
 %1cL%4c|%7c
 %1dM%4d}%7d
 %1eN%4e~%7e
 %1fO%4f %7f
space(空格)%20P%50%80
!%21Q%51 %81
"%22R%52%82
#%23S%53ƒ%83
$%24T%54%84
%%25U%55%85
&%26V%56%86
'%27W%57%87
(%28X%58ˆ%88
)%29Y%59%89
*%2aZ%5aŠ%8a
+%2b[%5b%8b
,%2c\%5cŒ%8c
-%2d]%5d %8d
.%2e^%5eŽ%8e
/%2f_%5f %8f

URL 编码 - 从 %90 到 %ff

ASCII ValueURL-encodeASCII ValueURL-encodeASCII ValueURL-encode
 %90À%c0ð%f0
%91Á%c1ñ%f1
%92Â%c2ò%f2
%93Ã%c3ó%f3
%94Ä%c4ô%f4
%95Å%c5õ%f5
%96Æ%c6ö%f6
%97Ç%c7÷%f7
˜%98È%c8ø%f8
%99É%c9ù%f9
š%9aÊ%caú%fa
%9bË%cbû%fb
œ%9cÌ%ccü%fc
 %9dÍ%cdý%fd
ž%9eÎ%ceþ%fe
Ÿ%9fÏ%cfÿ%ff
 %a0Ð%d0  
¡%a1Ñ%d1  
¢%a2Ò%d2  
£%a3Ó%d3  
 %a4Ô%d4  
¥%a5Õ%d5  
|%a6Ö%d6  
§%a7 %d7  
¨%a8Ø%d8  
©%a9Ù%d9  
ª%aaÚ%da  
«%abÛ%db  
¬%acÜ%dc  
¯%adÝ%dd  
®%aeÞ%de  
¯%afß%df  
°%b0à%e0  
±%b1á%e1  
²%b2â%e2  
³%b3ã%e3  
´%b4ä%e4  
µ%b5å%e5  
%b6æ%e6  
·%b7ç%e7  
¸%b8è%e8  
¹%b9é%e9  
º%baê%ea  
»%bbë%eb  
¼%bcì%ec  
½%bdí%ed  
¾%beî%ee  
¿%bfï%ef  
<think>嗯,用户问的是encodeURIComponent怎么解码。首先,我需要回忆一下encodeURIComponent的作用。它主要用于将字符编码为URI组件,替换某些字符为十六进制转义序列,比如空格变成%20。解码的话,应该用decodeURIComponent函数,对吧? 不过,我得确认用户是否真的了解编码和解码的基本概念。可能他们遇到了URL参数处理的问题,比如在获取编码后的参数时需要解码。或者他们可能在使用JavaScript处理数据时,需要对之前编码过的字符串进行解码。 用户的问题看起来比较直接,但可能需要更详细的步骤说明。比如,如何正确使用decodeURIComponent,以及使用时需要注意哪些地方,比如错误处理。因为如果传入的字符串不是有效的编码结果,decodeURIComponent会抛出异常,所以应该用try-catch块来捕获错误。 另外,用户可能没有意识到encodeURIComponent和encodeURI的区别,是否需要简要说明一下?比如encodeURI不会编码某些字符,如:/?#[]@,而encodeURIComponent会编码更多字符,适合用于URI的组成部分,比如查询参数。 还需要举例子,比如编码后的字符串是什么样的,解码后的结果如何。例如,编码"Hello World!"会得到"Hello%20World%21",解码后恢复原样。同时,要提醒用户不要对已经解码的字符串重复解码,否则可能出错。 可能用户在实际使用中遇到了解码后的字符串乱码或者错误,这时候需要考虑字符编码是否一致,比如UTF-8。或者他们的数据在传输过程中被多次编码,需要多次解码,但这种情况比较少见,一般是一次编码一次解码。 另外,是否要提到替代方法?比如unescape函数,但注意到unescape已经被废弃,不推荐使用,所以应该坚持使用decodeURIComponent。 总结一下,回答的结构应该是先说明解码函数是什么,然后给出用法示例,注意事项,可能的问题及解决方法,以及相关的知识点。这样用户不仅能解决问题,还能理解背后的原理,避免未来犯同样的错误。</think>--- ### 🔍 核心解答 `encodeURIComponent` 的对应解码方法是 **`decodeURIComponent()`**,这是 JavaScript 原生的 URL 解码函数,专门用于处理由 `encodeURIComponent` 生成的编码字符串。 --- ### 📌 核心用法 #### 基础解码示例 ```javascript // 编码示例 const encoded = encodeURIComponent("搜索词=天气&city=北京"); // 输出:"%E6%90%9C%E7%B4%A2%E8%AF%8D%3D%E5%A4%A9%E6%B0%94%26city%3D%E5%8C%97%E4%BA%AC" // 解码示例 const decoded = decodeURIComponent(encoded); // 输出:"搜索词=天气&city=北京" ``` #### 错误处理(必加防护) ```javascript try { const result = decodeURIComponent("%E0%A4%A"); // 非法编码片段 } catch(e) { console.error("解码失败:", e.message); // 捕获 URIError } ``` --- ### 🔥 关键注意事项 1. **编码范围差异** - `encodeURI`:保留完整 URL 结构(不编码 `;/?:@&=+$,#`) - `encodeURIComponent`:编码所有非标准字符(适合参数值) 2. **多层编码问题** ```javascript // 错误处理(双重编码情景) const doubleEncoded = encodeURIComponent(encodeURIComponent("上海")); // 正确解码方式 decodeURIComponent(decodeURIComponent(doubleEncoded)); // 需逐层解码 ``` 3. **特殊符号处理** | 原始字符 | 编码结果 | 解码还原 | |----------|----------|----------| | 空格 | `%20` | ✅ | | 中文"北" | `%E5%8C%97` | ✅ | | `+` 符号 | `%2B` | ✅ | --- ### 🛠️ 实战场景分析 #### 场景 1:URL 参数解析 ```javascript // 从 URL 获取参数:?q=%E6%9A%91%E6%9C%9F const params = new URLSearchParams(window.location.search); const keyword = decodeURIComponent(params.get("q")); // "暑期" ``` #### 场景 2:JSON 数据处理 ```javascript // 接收已编码的 JSON 字符串 const encodedData = '%7B%22name%22%3A%22%E5%BC%A0%E4%B8%89%22%7D'; const jsonStr = decodeURIComponent(encodedData); // {"name":"张三"} const data = JSON.parse(jsonStr); ``` --- ### ⚠️ 常见陷阱 1. **错误解码顺序** ```javascript // 错误:先组合后解码 const wrong = decodeURIComponent("id=" + encodedValue); // 正确:先解码后组合 const correct = "id=" + decodeURIComponent(encodedValue); ``` 2. **非法字符处理** ```javascript // 手动替换加号(某些服务端框架的兼容处理) const safeDecode = (str) => decodeURIComponent(str.replace(/\+/g, '%20')); ``` 3. **编码验证函数** ```javascript const isValidEncoding = (str) => { try { decodeURIComponent(str); return true; } catch { return false; } }; ``` --- ### 🌐 编码标准对照表 | 字符类型 | encodeURIComponent 表现 | 示例结果 | |------------------|--------------------------|----------------------| | ASCII 字母数字 | 不编码 | `a-z` → `a-z` | | 保留字符 | 编码 | `!` → `%21` | | 非 ASCII 字符 | UTF-8 编码 | `中文` → `%E4%B8%AD%E6%96%87` | | 特殊符号 | 完全编码 | `\n` → `%0A` | --- ### 🔧 进阶工具函数 #### 自动容错解码 ```javascript function safeDecodeURIComponent(str) { try { return decodeURIComponent(str); } catch { // 使用替换策略处理非法片段 return str.replace(/%([0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值