与Prototype.js的JSON.stringify()数组奇异性

mor*_*des 83 javascript json prototypejs

我正在试图找出我的json序列化出了什么问题,使用我的应用程序的当前版本和旧版本,并且在JSON.stringify()的工作方式中发现了一些令人惊讶的差异(使用来自json.org的JSON库) ).

在我的应用程序的旧版本中:

 JSON.stringify({"a":[1,2]})
Run Code Online (Sandbox Code Playgroud)

给了我这个;

"{\"a\":[1,2]}"
Run Code Online (Sandbox Code Playgroud)

在新版本中,

 JSON.stringify({"a":[1,2]})
Run Code Online (Sandbox Code Playgroud)

给了我这个;

"{\"a\":\"[1, 2]\"}"
Run Code Online (Sandbox Code Playgroud)

任何想法可以改变什么使相同的库在新版本的数组括号周围放置引号?

Rap*_*ert 77

由于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;
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,处理该问题所需的唯一语句是:delete Array.prototype.toJSON (11认同)

Jea*_*ent 77

ECMAScript 5及更高版本(第201页 - JSON对象,伪代码页面205)中定义的函数JSON.stringify()在对象上可用时使用函数toJSON().

因为Prototype.js(或您正在使用的另一个库)定义了一个Array.prototype.toJSON()函数,所以首先使用Array.prototype.toJSON()然后使用JSON.stringify()引用的字符串将数组转换为字符串,因此数组周围的引号不正确.

因此,解决方案是直截了当且简单的(这是Raphael Schweikert答案的简化版本):

delete Array.prototype.toJSON
Run Code Online (Sandbox Code Playgroud)

这产生了对依赖于数组的toJSON()函数属性的库的副作用.但考虑到与ECMAScript 5的不兼容性,我发现这是一个小小的不便.

必须注意的是,ECMAScript 5中定义的JSON对象在现代浏览器中有效实现,因此最佳解决方案是符合标准并修改现有库.

  • 对于数组的额外引用,这是最简洁的答案. (5认同)

akk*_*ore 14

一个不会影响其他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;
};
Run Code Online (Sandbox Code Playgroud)

这会处理与JSON.stringify不兼容的Array toJSON,并且还会保留toJSON功能,因为其他Prototype库可能依赖于它.

  • 我包装成`if(typeof Prototype!=='undefined'&& parseFloat(Prototype.Version.substr(0,3))<1.7 && typeof Array.prototype.toJSON!=='undefined')`.有效. (2认同)

Bob*_*Bob 8

编辑以使其更准确:

代码的问题关键位在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库.

  • 这不是库中的错误,因为这是在ECMAScript 5中定义JSON.stringify()的确切方法.问题在于prototype.js,解决方案是:delete Array.prototype.toJSON这将有一些方面原型toJSON序列化的效果,但我发现这些与原型与ECMAScript 5的不兼容性有关. (2认同)