轻量级和旧浏览器兼容的纯javascript JSON替代方案



我得到一个文本响应从我的服务器存储在一个javascript变量。我有这个响应的格式完全控制。通常这个文本响应有3个元素,我需要,理想情况下,我想使用json.parse来解决我的问题,如:

var json = '{"result":true,"count":1, "state":"ON"}',
obj = JSON.parse(json);
alert(obj.result);
alert(obj.count);
alert(obj.state);

优雅和简单,但旧的浏览器,如IE8,7,6不支持json.parse。在这一点上,我有两个可能的解决方案,一个当然是使用Jquery,但我不想,因为我想保持我的代码尽可能小,两个可以使用一个库,如json2,为我处理不兼容的问题,像Jquery一样,但再次,同样的问题,太多的代码为这样一个简单的功能。

所以我认为最好的方法是将响应格式更改为true%1%ON之类的内容,然后围绕%拆分,您认为如何?我觉得有点脏。

您可以从现有的库中取出解析器的代码,而不是拥有所有的代码,因为您只需要解析器。一个例子是从jQuery核心中取出$.parseJSON的实现(第523-551行)。显然,它使用new Function方法而不是eval

在我因没有阅读问题而受到斥责之前,让我重新措辞:

使用json2.js库,在我看来(这并不重要),不会导致显著的性能损失,也不会包含很多代码,特别是当最小化时:

if(typeof JSON!=="object"){JSON={}}(function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){escapable.lastIndex=0;return escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t==="string"?t:"\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];if(a&&typeof a==="object"&&typeof a.toJSON==="function"){a=a.toJSON(e)}if(typeof rep==="function"){a=rep.call(t,e,a)}switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a){return"null"}gap+=indent;u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n<s;n+=1){u[n]=str(n,a)||"null"}i=u.length===0?"[]":gap?"[n"+gap+u.join(",n"+gap)+"n"+o+"]":"["+u.join(",")+"]";gap=o;return i}if(rep&&typeof rep==="object"){s=rep.length;for(n=0;n<s;n+=1){if(typeof rep[n]==="string"){r=rep[n];i=str(r,a);if(i){u.push(quote(r)+(gap?": ":":")+i)}}}}else{for(r in a){if(Object.prototype.hasOwnProperty.call(a,r)){i=str(r,a);if(i){u.push(quote(r)+(gap?": ":":")+i)}}}}i=u.length===0?"{}":gap?"{n"+gap+u.join(",n"+gap)+"n"+o+"}":"{"+u.join(",")+"}";gap=o;return i}}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(e){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(e){return this.valueOf()}}var cx=/[u0000u00adu0600-u0604u070fu17b4u17b5u200c-u200fu2028-u202fu2060-u206fufeffufff0-uffff]/g,escapable=/[\"x00-x1fx7f-x9fu00adu0600-u0604u070fu17b4u17b5u200c-u200fu2028-u202fu2060-u206fufeffufff0-uffff]/g,gap,indent,meta={"b":"\b","   ":"\t","n":"\n","f":"\f","r":"\r",'"':'\"',"\":"\\"},rep;if(typeof JSON.stringify!=="function"){JSON.stringify=function(e,t,n){var r;gap="";indent="";if(typeof n==="number"){for(r=0;r<n;r+=1){indent+=" "}}else if(typeof n==="string"){indent=n}rep=t;if(t&&typeof t!=="function"&&(typeof t!=="object"||typeof t.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":e})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){function walk(e,t){var n,r,i=e[t];if(i&&typeof i==="object"){for(n in i){if(Object.prototype.hasOwnProperty.call(i,n)){r=walk(i,n);if(r!==undefined){i[n]=r}else{delete i[n]}}}}return reviver.call(e,t,i)}var j;text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(e){return"\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})}if(/^[],:{}s]*$/.test(text.replace(/\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\nr]*"|true|false|null|-?d+(?:.d*)?(?:[eE][+-]?d+)?/g,"]").replace(/(?:^|:|,)(?:s*[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}})()

你可以只用一行就把它放进去,然后就完成了。为已经完成的东西编写自己的语法会占用大量的时间,而不是完成其他工作来完成项目。您将编写的任何代码都必须经过与此json库相同的严格测试,该库已经过时间测试并证明有效。

这一行代码是3KB文件。

json on github

嗯,就像你说的,你有两个选择:

  • 要么包含一个像JSON2这样的库(它是17KB未压缩的,所以不是一个很大的负担)
  • 构建自己的小解析器

然后还有第三个选项,这是潜在的安全问题,但它可能会:使用eval对json求值:

var json = '{"result":true,"count":1, "state":"ON"}';
obj = eval(json);

您可以试试json-sans-eval。它又快又小(只有1.5Kb),但是不验证JSON。

最新更新