如何理解 JSON.parse() 里的转义符呢?

。。。 有人问了我这个问题。。 我也不是很清楚

JSON.parse(`{
    "test": "这是一个对象, 里面有 test 字段"
}`)

上面可以正常运行。。 结果是 {test: "这是一个对象, 里面有 test 字段"}

clipboard.png


但是 如果 test 字段里面加上 双引号 就有很奇妙的问题..

JSON.parse(`{
    "test": "这是一个对象, 里面有 "test" 字段"
}`)

上述会报错 这很正常。

clipboard.png

现在加入转义符

JSON.parse(`{
    "test": "这是一个对象, 里面有 \"test\" 字段"
}`)

结果依然报错,即使我直接输入这种字符串可以正常显示转义后的字符串,如图:

clipboard.png


奇妙的是。。 我不小心写了这样的代码,使用 \\ 作为转义符而不是 \。。。 结果却是正常的。

clipboard.png


But Why ?

阅读 11.7k
3 个回答

应该是因为 JSON.parse 的执行过程其实经历了两次转义吧。

一次是字符串本身的转义:

'{"test": "这是一个对象, 里面有 \\"test\\" 字段"}'

被转换成

'{"test": "这是一个对象, 里面有 \"test\" 字段"}'

(可以直接在浏览器的命令行输入这段字符串)

一次是字符串转对象时的转义:

因为已经被转换成了

'{"test": "这是一个对象, 里面有 \"test\" 字段"}'

"\"会被认为是 """的转义符,就会正确的转成对象。

而当只有一个"\"的时候,到字符串转对象的时候, test 字段值里就有两对双引号,就会报错。

又去查了下 ES5 规范中的 parse 方法:

clipboard.png

第一步应该是对应字符串本身的转义

第二步则对应字符串转对象时的转义

这里存在两次转义

第一次是在定义字符串的时候,把字面的 \\ 转义成了 \。因为这次是用的反单引号引用字符串(字符串模板),里面的双引号 " 不需要转义。这次转义是 JS 的字符串转义。

JSON.Parse 会对 JSON 字符串进行转义,而且 JSON 中使用双引号表示字符串。这里因为是用双引号表示字符串,所以字符串内的双引号需要用 \ 转义,也就是第一步转义出来的 \,及其后的 " 合并成 \",被转义成 "。这就是 parse 结果里的属性值中的引号。

JSON.parse(`{
    "test": "这是一个对象, 里面有 test 字段"
}`);

用到了ES6中的模板字符串的特性,
相当于

JSON.parse('{"test": "这是一个对象, 里面有 test 字段"}');

JSON.parse("{\"test\": \"这是一个对象, 里面有 test 字段\"}");

JS引擎首先检查是否有字符串语法错误,也就是是否能正确的解析为字符串
其中的\转义符号,告诉解析器,后面的"是json格式文本的一部分,而不是parse字符串参数的一部分
经过这个步骤,parse参数值为{"test": "这是一个对象, 里面有 test 字段"},为合法的JSON格式文本

而如果在test对应的值中还有",在不转义的情况下
"{\"test\": \"这是一个对象, 里面有 "test" 字段\"}"本身就是一个不合法的字符串

将其变成合法的,要修改为"{\"test\": \"这是一个对象, 里面有 \"test\" 字段\"}",
JS引擎编译解析的值为{"test": "这是一个对象, 里面有 "test" 字段"}

But这个值为非法的JSON格式文本,需要对值中的"进行再次转义,
"{\"test\": \"这是一个对象, 里面有 \\\"test\\\" 字段\"}",
JS引擎编译解析的值为{"test": "这是一个对象, 里面有 \"test\" 字段"},这个值为格式正确的JSON文本

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏