我正在试图找出我的json序列化出了什么问题,使用我的应用程序的当前版本和旧版本,并且在JSON.stringify()的工作方式中发现了一些令人惊讶的差异(使用来自json.org的JSON库) ).
在我的应用程序的旧版本中:
JSON.stringify({"a":[1,2]})
给了我这个;
"{\"a\":[1,2]}"
在新版本中,
JSON.stringify({"a":[1,2]})
给了我这个;
"{\"a\":\"[1, 2]\"}"
任何想法可以改变什么使相同的库在新版本的数组括号周围放置引号?
由于JSON.stringify最近已经与一些浏览器一起发布,我建议使用它而不是Prototype的toJSON.然后,您将检查window.JSON && window.JSON.stringify,否则只包含json.org库(通过document.createElement('script')
...).要解决不兼容问题,请使用:
if(window.Prototype) { delete Object.prototype.toJSON; delete Array.prototype.toJSON; delete Hash.prototype.toJSON; delete String.prototype.toJSON; }
ECMAScript 5及更高版本(第201页 - JSON对象,伪代码页面205)中定义的函数JSON.stringify()在对象上可用时使用函数toJSON().
因为Prototype.js(或您正在使用的另一个库)定义了一个Array.prototype.toJSON()函数,所以首先使用Array.prototype.toJSON()然后使用JSON.stringify()引用的字符串将数组转换为字符串,因此数组周围的引号不正确.
因此,解决方案是直截了当且简单的(这是Raphael Schweikert答案的简化版本):
delete Array.prototype.toJSON
这产生了对依赖于数组的toJSON()函数属性的库的副作用.但考虑到与ECMAScript 5的不兼容性,我发现这是一个小小的不便.
必须注意的是,ECMAScript 5中定义的JSON对象在现代浏览器中有效实现,因此最佳解决方案是符合标准并修改现有库.
一个不会影响其他Prototype依赖的可能解决方案是:
var _json_stringify = JSON.stringify; JSON.stringify = function(value) { var _array_tojson = Array.prototype.toJSON; delete Array.prototype.toJSON; var r=_json_stringify(value); Array.prototype.toJSON = _array_tojson; return r; };
这会处理与JSON.stringify不兼容的Array toJSON,并且还会保留toJSON功能,因为其他Prototype库可能依赖于它.
编辑以使其更准确:
代码的问题关键位在JSON.org的JSON库中(以及ECMAScript 5的JSON对象的其他实现):
if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); }
问题是Prototype库扩展了Array以包含一个toJSON方法,JSON对象将在上面的代码中调用该方法.当JSON对象命中数组值时,它会调用Prototype中定义的数组上的JSON,并且该方法返回数组的字符串版本.因此,数组括号周围的引号.
如果从Array对象中删除toJSON,则JSON库应该可以正常工作.或者,只使用JSON库.