【奇技淫巧】异常JSON字符串解析问题


经常我们会遇到后端返回的数据JSON的格式不正常,会出现key没有引号的情况,如:

var str = '{a: 1, b: 2}';

当然,这种情况可以让后端修改返回数据格式,但是往往再面试或则其他时候有可能会问道:如何去解析这种类型的字符串?

毕竟分类是在奇技淫巧中,那常规的evalnew Function这里就不多说。

方式一:[native code].constructor

使用JS内置对象的任意原型方法,如:Object.prototype.toStringArray.prototype.pushRegExp.prototype.test等等,其实这里的实质原理还是new Function

Object.prototype.toString.constructor === Function // true
Array.prototype.push.constructor === Function // true
RegExp.prototype.test.constructor === Function // true
var json = '{a: 1, b: 2}';
json = 'window.result = ' + json; // 严格模式下eval有自己的作用于,直接var接受JSON是获取不到值的,需要挂载再window全局下面
Object.prototype.toString.constructor(json)(); // 1
console.log(result); // {a: 1, b: 2}

方式二:script标签 + innerHTML

直接插入script标签,同时把字符串拼接一个接受的变量innerHTML进去。

var json = '{a: 1, b: 2}';
var script = document.createElement('script');
script.innerHTML = 'var result = ' + json;
document.body.appendChild(script);
console.log(result); // {a: 1, b: 2}

方式三:script标签 + src

字符串通过blob可以转二进制,再通过window.URL.createObjectURL转url。

var json = '{a: 1, b: 2}';
var blob = new Blob(['var result = ' + json]);
var src = window.URL.createObjectURL(blob);
var script = document.createElement('script');
script.src = src;
document.body.appendChild(script);
script.onload = function(){
  console.log(result); // {a: 1, b: 2}
}

PS:由于是src加载的,需要再onload才能获取到数据,同时有blob转的url,需要在有服务器的条件下才能测试,直接打开一个本地html文件无法测试,需要测试的可以直接打开一个百度什么的网站,F12在控制台测试。

方式四:Worker

同上一条一样创建url,然后通过Worker运行,但是这里接受数据就只能通过postMessageonmessage

var json = '{a: 1, b: 2}';
var blob = new Blob(['postMessage(' + json + ')']);
var src = window.URL.createObjectURL(blob);
var worker = new Worker(src);
worker.onmessage = function(e){
  console.log(e.data); // {a: 1, b: 2}
}

PS:同上,需要再服务器的条件下测试。

方式五:location.href

经常我们再写点击事件的时候会这样写:

<a href="javascript:void 0;">
<div onclick="javascript:alert(1)"></div>

同时随便打开一个页面,再地址栏输入:javascript:alert(1),可以看到,代码执行了,并且页面并没有跳转变化,SO,我们可以利用这一点。

PS:复制到地址栏默认会去掉javascript:,需要手动补上。

var json = '{a: 1, b: 2}';
location.href = 'javascript:var result = ' + json;
setTimeout(function(){
  console.log(result); // {a: 1, b: 2}
}, 0);

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>