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("\\\\", "\\\\\\\\")