一、问题
今天小程序线上,有客户反映在购买一本名为《习近平的七年知青岁月》的书籍时,出现点击提交订单时页面数据丢失的情况。
经过反复排查,发现是由于这本书籍查询出来的实体中包含一个字段,字段的值包含了特殊字符“=”号。而这个实体对象,在小程序端,我们是通过 JSON.stringify
和JSON.parse
来在页面之间传递对象数据的,众所周知,JSON.parse
这个js方法,解析特殊的字符串会抛错。
那么问题就来了,这也是广大前端程序员会埋怨的一个坑:怎么解决JSON.parse
无法解析特殊字符串的问题?
二、基础详解
JSON.stringify
用于将 JavaScript 值转换为 JSON 字符串。
语法:
JSON.stringify(value[, replacer[, space]])
参数说明:
-
value:必需, 要转换的 JavaScript 值(通常为对象或数组)。
-
replacer:可选。用于转换结果的函数或数组。如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。
-
space:可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。
返回值:返回包含 JSON 文本的字符串。
用法:
let order = [];
order.push(goods);
let orderJsonStr = JSON.stringify(order); //将order对象转化为字符串
JSON.parse
用于将一个 JSON 字符串转换为对象。
语法
JSON.parse(text[, reviver])
参数说明:
- text:必需, 一个有效的 JSON 字符串。
- reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
返回值:返回给定 JSON 字符串转换后的对象。
用法:
dataSoure = JSON.parse(options.orders); //将order字符串转化为对象
encodeURIComponent
把字符串作为 URI 组件进行编码。
语法:
encodeURIComponent(URIstring)
参数说明:
- URIstring:必需。一个字符串,含有 URI 组件或其他要编码的文本。
返回值:URIstring 的副本,其中的某些字符将被十六进制的转义序列进行替换。
说明:该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码:- _ . ! ~ * ' ( )
。
其他字符(比如 :;/?:@&=+$,#
这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
例子:
<script type="text/javascript">
document.write(encodeURIComponent("http://www.w3school.com.cn"))
document.write("<br />")
document.write(encodeURIComponent("http://www.w3school.com.cn/p 1/"))
document.write("<br />")
document.write(encodeURIComponent(",/?:@&=+$#"))
</script>
输出:
http%3A%2F%2Fwww.w3school.com.cn
http%3A%2F%2Fwww.w3school.com.cn%2Fp%201%2F
%2C%2F%3F%3A%40%26%3D%2B%24%23
encodeURI
把字符串作为 URI 进行编码。
语法:
encodeURI(URIstring)
参数说明:
- URIstring :必需。一个字符串,含有 URI 或其他要编码的文本。
返回值:URIstring 的副本,其中的某些字符将被十六进制的转义序列进行替换。
说明:该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( )
。该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?:@&=+$,#
例子:
<script type="text/javascript">
document.write(encodeURI("http://www.w3school.com.cn")+ "<br />")
document.write(encodeURI("http://www.w3school.com.cn/My first/"))
document.write(encodeURI(",/?:@&=+$#"))
</script>
输出:
http://www.w3school.com.cn
http://www.w3school.com.cn/My%20first/
,/?:@&=+$#
decodeURIComponent
decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码。
语法:
decodeURIComponent(URIstring)
参数说明:
- URIstring : 必需。一个字符串,含有编码 URI 组件或其他要解码的文本。
返回值:URIstring 的副本,其中的十六进制转义序列将被它们表示的字符替换。
例子:
<script type="text/javascript">
var test1="http://www.w3school.com.cn/My first/"
document.write(encodeURIComponent(test1)+ "<br />")
document.write(decodeURIComponent(test1))
</script>
输出:
http%3A%2F%2Fwww.w3school.com.cn%2FMy%20first%2F
http://www.w3school.com.cn/My first/
decodeURI
decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码。
语法:
decodeURI(URIstring)
参数说明:
- URIstring: 必需。一个字符串,含有要解码的 URI 或其他要解码的文本。
返回值:URIstring 的副本,其中的十六进制转义序列将被它们表示的字符替换。
例子:
<script type="text/javascript">
var test1="http://www.w3school.com.cn/My first/"
document.write(encodeURI(test1)+ "<br />")
document.write(decodeURI(test1))
</script>
输出:
http://www.w3school.com.cn/My%20first/
http://www.w3school.com.cn/My first/
三、解决办法
从上面的基础函数了解到,encodeURIComponent
方法包含的解码特殊字符串包含了我线上遇到的字符“=”号,所以解决办法就来了。JSON.stringify
后编码,JSON.parse
前转码。
编码:
let order = [];
order.push(goods);
let orderJsonStr = JSON.stringify(order);
//encodeURIComponent(orderJsonStr) 进行编码
wx.navigateTo({
url: '../ConfirmOrder/ConfirmOrder?orders=' + encodeURIComponent(orderJsonStr)
})
转码:
onLoad: function (options) {
let order = JSON.parse(decodeURIComponent(options.orders)); //转码
...
}