Javascript解析JSON字符串报错:parse failed: SyntaxError: Unexpected token n in 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("\\\\", "\\\\\\\\")