Javascript解析JSON字符串报错:parse failed: SyntaxError: Unexpected token n in JSON
一个嵌套json串引发的事故
问题背景
有个JavaScript对象obj,其中一个属性值为另一个对象child的JSON stringify后得到的JSON字符串。
大概是这样子
var child = {
number: 123,
string: "abc"
};
var childValue = JSON.stringify(child);
var obj = {
data: [
{
key: "mykey",
value: childValue
}
]
}
obj对象的数据被JSON化后存储在服务器上,读取时,服务器也用JSON格式发送obj对象数据。
但是,奇怪的是,在对服务端获取的obj JSON数据进行解析时,报错了
parse failed: SyntaxError: Unexpected token n in JSON at position 54
这是为什么呢?
解决方法
为了解决这个问题,写了一个简单的js测试用例,如下。
try{ var child = { number: 123, string: "abc" }; var childValue = JSON.stringify(child); var obj = { data: [ { key: "mykey", value: childValue } ] }var objJson = JSON.stringify(obj); console.info("child json ===> ", childValue); console.info("=============================\n"); console.info("obj json ===> ", objJson); console.info("=============================\n"); var b = JSON.parse(objJson); console.info("obj parse from json => ", b); console.info("=============================\n"); var objJson3 = ` { "data":[ { "key":"mykey", "value":"{\\\"number\\\":123,\\\"string\\\":\\\"abc\\\"}" }] } `; var objJson2 = ` { "data":[ { "key":"mykey", "value":"{\"number\":123,\"string\":\"abc\"}" }] } `; var c = JSON.parse(objJson3); console.info("obj3 parse from json => ", c); console.info("=============================\n"); c = JSON.parse(objJson2); console.info("obj2 parse from json => ", c); console.info("=============================\n"); // var v = b.data[0].value; // console.info("value: ", v); // var vo = JSON.parse(v); // console.info("value to object: ", vo);
}catch(e){ console.info(“parse failed: “,e); }
运行结果
node test.js child json ===> {"number":123,"string":"abc"} =============================obj json ===> {“data”:[{“key”:“mykey”,“value”:“{"number":123,"string":"abc"}”}]}
obj parse from json => { data: [ { key: ‘mykey’, value: ’{“number”:123,“string”:“abc”}’ } ] }
obj3 parse from json => { data: [ { key: ‘mykey’, value: ’{“number”:123,“string”:“abc”}’ } ] }
parse failed: SyntaxError: Unexpected token n in JSON at position 54 at JSON.parse (<anonymous>) at Object.<anonymous> (/Users/zhangzhibin/Documents/mygit/temp/test.js:54:11) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) at internal/main/run_main_module.js:17:47
发现,从服务端读取的obj数据是objJson2,该数据中,child的json串中增加了一些转义字符(由斜杆\开头)。
这是正常的,JSON字符串需要对特殊字符进行转义才能保存。
而报错的位置,正是第一个转移字符:

仔细分析一下,JavaScript的JSON.parse在解析时,可能先对字符串中的转义字符进行转义,其中
\" => "
所以,objJson2等同于
var objJson2 = `
{
"data":[
{
"key":"mykey",
"value":"{"number":123,"string":"abc"}"
}]
}
`;
而这,显然不是一个合法的JSON串了。
同理,对于objJson3,对转义字符进行一次处理:
\\ => \
\" => "
得到:
var objJson3 = `
{
"data":[
{
"key":"mykey",
"value":"{\"number\":123,\"string\":\"abc\"}"
}]
}
`;
这是一个合法的嵌套了JSON串的JSON串。
如何处理这种情况
有几个方案:
-
- 对特殊字符串进行编码
例如,在保存的时候,将内嵌的json串进行base64编码,在读取后,进行base64解析。
- 对特殊字符串进行编码
-
- 在读取时对转义字符进行二次转义
例如,将服务端读取的字符串中
- 在读取时对转义字符进行二次转义
\ 替换成 \\
注意,如果在java中使用这种方案,需要
strBsf.replaceAll("\\\\", "\\\\\\\\")