关于querystring.parse解析字符串‘+’号的问题思考

2,128 阅读2分钟

现在有一个待解析的字符串,例如

const str = 'a=1+2&b=1'

希望用node自带的querystring.parse函数解析,预计获得这样的结果

{
  a: '1+2',
  b: '1'
}

然而实际的结果却是

querystring.parse(str)
// { a: '1 2', b: '1' }

问题点:为什么+号被解析成了空格?

querystring.parse源码分析

源码地址: github.com/nodejs/node…

思路大致分析(以一个简单字符串解析为例):

querystring.parse('a=1+1&b=2')

  • 获取默认分隔符和等号(unicode编码)

    const sepCodes = [38] // '&'

    const eqCodes = [61]; // '='

  • 遍历传入的字符串('a=1+1&b=2')

  • 判断当前是否为分割符 - 字符unicode === 38,或判断当前是否为赋值符号 - unicode === 61

  • 若是,对其进行分割操作,为后续取key,v做一些工作

  • 判断当前字符是否为 ‘+’

  • 若是,则替换成‘ ’ (以此时传入querystring.parse的参数来说)

image.png

当前方案如何解决该问题

若不改变目前已拥有的字符串,通过何种方式能获取我们所需的对象呢

解决方案: 事先先将 + 号手动替换成%2B , 或者自己写一个解析函数

querystring.parse('a=1+1&b=2'.replace(/\+/g, '%2B'))
// 事先将+号替换成%2B,内部对获取的value还会做一次decode

为什么querystring.parse要将+号处理成’ ‘呢?为什么不是‘ - ’号

关于空格的编码,目前存在两种

  • html4定义: 空格应该被编码成加号"+",而如果字符本身就是加号"+",则应该被编码成%2B

  • RFC-3986定义: 采用统一的编码方式,字符的编码格式为:%HH(H为十六进制字符), 并没有对空格做特殊处理。按照RFC-3986规范,空格被编码成%20,而加号"+"被编码成%2B。

因此,可以理解为何parse时会对+号做特殊处理