Open YvetteLau opened 5 years ago
var A = "{ a: 1 , b : 'hello' }";
var B = "{ 'a': 1 , 'b' : 'hello' }";
var C = "{'a':1,'b':'hello'}";
var D = '{"a":1,"b":"hello"}';
var E = '{ "a" : 1 , "b" : "hello" }';
var E = '{ "a" : 1 , "b" : "sadfsf" }';
var F = '{ "a" : 1 ,\n "b" : "hello" }';
var G = '{ "a" : 1 , "b" : window.location.href="https://www.baidu.com" }';
//JSON.parse() A,B,C,G都不可转, D,E,F可以转换
//eval() 都可以转, G还执行了G.b的代码
function jsonParse(str) {
if(!str || str.constructor !== String || str.indexOf(':') === -1){
return {};
}else{
let tempStr = str.replace(/'|"| |{|}/ig, '');
let tempArr = tempStr.split(',');
let returnObj = {};
tempArr.map( item => {
returnObj[item.slice(0, item.indexOf(':'))] = item.slice(item.indexOf(':') + 1, item.length);
});
console.log(returnObj);
}
}
jsonParse(A);
var A = "{ a: 1 , b : 'hello' }";
var B = (new Function('return'+ A))()
B 结果为 :{a: 1, b: "hello"}
eval
// 只能处理格式正确且不含空格的json
function jsonParse(json) {
i = 0;
str = json;
return parseValue();
}
function parseValue() {
if(str[i]==='n') {
return parseNull();
} else if(str[i]==='t') {
return parseTrue();
} else if(str[i]==='f') {
return parseFalse();
} else if(str[i]==='"') {
return parseString();
} else if(str[i]==='[') {
return parseArray();
} else if(str[i]==='{') {
return parseObject();
} else {
return parseNumber();
}
}
function parseSpace() {
while(str[i]==' ') {
i++;
}
}
function parseNull() {
let content = str.substring(i, i+4);
// let content = str.substr(i, 4);
if(content==='null') {
i+=4;
return null;
} else {
throw new Error('Unexpected char at pos: ' + i);
}
}
function parseTrue() {
let content = str.substring(i, i+4);
// let content = str.substr(i, 4);
if(content==='true') {
i+=4;
return true;
} else {
throw new Error('Unexpected char at pos: ' + i);
}
}
function parseFalse() {
let content = str.substring(i, i+5);
// let content = str.substr(i, 5);
if(content==='false') {
i+=5;
return false;
} else {
throw new Error('Unexpected char at pos: ' + i);
}
}
function parseString() {
i++;
let result = '';
while(str[i]!=='"') {
result += str[i++];
}
i++;
return result;
}
function parseArray() {
i++;
let result = [];
while(str[i]!==']') {
result.push(parseValue());
if(str[i] ===',') {
i++;
}
}
i++;
return result;
}
function parseObject() {
i++;
let result = {};
while(str[i]!=='}') {
let key = parseString();
i++; // 略过一个冒号(:)
let value = parseValue();
result[key] = value;
if(str[i]===',') i++;
}
i++;
return result;
}
function parseNumber() {
let result = '';
while(isNumberChar(str[i])) {
result += str[i++];
}
return parseFloat(result);
}
function isNumberChar(c) {
let chars = {
'+': true,
'-': true,
'e': true,
'E': true,
'.': true
}
if(chars[c]) {
return true;
}
if(c>='0'&&c<='9') {
return true;
} else {
return false;
}
}
const test = '{"a":1,"b":true,"c":false,"foo":null,"bar":[1,2,3]}';
console.log(jsonParse(test));
最简单,最直观的方式就是调用 eval
var json = '{"name":"小姐姐", "age":20}';
var obj = eval("(" + json + ")"); // obj 就是 json 反序列化之后得到的对象
直接调用 eval
存在 XSS
漏洞,数据中可能不是 json
数据,而是可执行的 JavaScript
代码。因此,在调用 eval
之前,需要对数据进行校验。
var rx_one = /^[\],:{}\s]*$/;
var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
if (
rx_one.test(
json
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
var obj = eval("(" +json + ")");
}
JSON
是 JS 的子集,可以直接交给 eval
运行。
new Function
Function
与 eval
有相同的字符串参数特性。
var json = '{"name":"小姐姐", "age":20}';
var obj = (new Function('return ' + json))();
var jsonStr = '{"age":20,"name":"jack"}'
var json = (new Function('return '+jsonStr))()
console.log(typeof json)
2.利用eval
var rx_one = /^[\],:{}\s]*$/;
var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
if (
rx_one.test(
json
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
var obj = eval("(" +json + ")");
}
// eval 是最简单的方法,可是不太懂为什么eval中要加个“(”、“)”
var json = '{"name":"小姐姐", "age":20}';
var obj = eval("(" + json + ")");
实现一个json.parse()
方式一 eval() 看见楼上的小姐姐提了一个eval("("+params+")"),为什么要用“()”去包裹参数,这个问题,我最初面向google搜索引擎 去研究了下 发现google不如国产百度好用,于是我面向国产百度搜索引擎去研究了下,得到的结论是,eval 接收可执行的js脚本或代码块,但不接受不可运行的js脚本作为参数"()"是让eval 把参数作为表达式去解析.
例如:
var json = '{"name":"蔡徐坤","age":"99“}'
console.log(eval("("+ json +")")) // {"name":"蔡徐坤","age":"99“}
方式二 函数
var jsond = '{"name":"蔡徐坤","age":"99"}'
var result = (new Function('return'+ jsond))()
console.log(result) //
JSON.parse() 方法解析一个JSON字符串,可将JSON字符串转化为对象。 JSON.parse(text [, reviver]) //第一个参数必填,一个有效的JSON字符串 第二个参数选题 是一个函数, 它用来转换已经被从text字符串转为对象的对象。对应的规则格式如下: (1)如果reviver返回的是一个有效值,则对应的属性值将替换为转换后的值。 (2)如果reviver返回的值与它接收的相同值,则不修改对应属性值。 (3)如果reviver返回的是undefined,则删除对应的属性。