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

     2023-03-31     302

关键词:

【中文标题】JSON.stringify() 数组的怪异与 Prototype.js【英文标题】:JSON.stringify() array bizarreness with Prototype.js 【发布时间】:2012-11-25 02:06:51 【问题描述】:

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

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

 JSON.stringify("a":[1,2])

给我这个;

"\"a\":[1,2]"

在新版本中,

 JSON.stringify("a":[1,2])

给我这个;

"\"a\":\"[1, 2]\""

知道什么可以改变以使相同的库在新版本中的数组括号周围加上引号?

【问题讨论】:

看起来与我们在较新版本中引入的 Prototype 库有冲突。任何想法如何在 Prototype 下对包含数组的 json 对象进行字符串化? 这就是为什么人们应该避免使用全局内置对象(就像原型框架所做的那样) 【参考方案1】:

由于 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;

【讨论】:

无需在您自己的代码中检查 window.JSON - json.org 脚本会自行完成这项工作 可能是这样,但是即使不需要,也必须加载整个脚本文件。 其实处理这个问题唯一需要的语句就是:delete Array.prototype.toJSON 非常感谢。我现在工作的公司目前仍在我们的大部分代码中使用原型,这是使用更现代的库的救命稻草,否则一切都会崩溃。 我一直在寻找 DAYS 的这个答案,并发布了两个不同的 SO 问题试图弄清楚。当我输入第三个时,将此视为一个相关问题。非常感谢!【参考方案2】:

ECMAScript 5 and above (Page 201 - the JSON Object, pseudo-code Page 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 对象在现代浏览器中是有效实现的,因此最好的解决方案是符合标准并修改现有的库。

【讨论】:

这是对数组的额外引用的最简洁的答案。【参考方案3】:

一个不会影响其他原型依赖的可能解决方案是:

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;
;

这解决了 Array toJSON 与 JSON.stringify 的不兼容问题,并且还保留了 toJSON 功能,因为其他 Prototype 库可能依赖它。

【讨论】:

我在一个网站中使用了这个 sn-p。它正在引起问题。它导致数组的 toJSON 属性未定义。对此有任何指示吗? 在使用上面的 sn-p 重新定义 JSON.stringify 之前,请确保您的 Array.prototype.toJSON 已定义。它在我的测试中运行良好。 我进入了if(typeof Prototype !== 'undefined' && parseFloat(Prototype.Version.substr(0,3)) < 1.7 && typeof Array.prototype.toJSON !== 'undefined')。它奏效了。 太棒了。直到 Prototype 1.7 才有这个问题。请点赞:) 问题是针对版本 【参考方案4】:

编辑以使其更准确:

问题的关键代码位在 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 中定义的数组上调用 toJSON,并且该方法返回数组的字符串版本。因此,数组括号周围的引号。

如果您从 Array 对象中删除 toJSON,JSON 库应该可以正常工作。或者,只需使用 JSON 库。

【讨论】:

这不是库中的错误,因为这是在 ECMAScript 5 中定义 JSON.stringify() 的确切方式。问题出在prototype.js 上,解决方案是:删除数组。 prototype.toJSON 这会对原型 toJSON 序列化产生一些副作用,但我发现这些是关于原型与 ECMAScript 5 不兼容的小问题。 Prototype 库没有扩展 Object.prototype 而是 Array.prototype,虽然 JavaScript 中的 typeof 数组也返回“object”,但它们没有相同的“构造函数”和原型。要解决这个问题你需要:“delete Array.prototype.toJSON;” @Jean 公平地说,Prototype 扩展了所有基础原生对象,包括 Object。但是好的,我再次明白了你的意思:) 感谢您帮助我的回答变得更好 Prototype 已经停止扩展“Object.prototype”很长时间了(我不记得是哪个版本)以避免 for .. in 问题。它现在仅将 Object 的静态属性(更安全)扩展为命名空间:api.prototypejs.org/language/Object Jean,实际上这正是库中的一个错误。如果一个对象有 toJSON,则必须调用它并且必须使用它的结果,但它不应该被引用。【参考方案5】:

我认为更好的解决方案是在加载原型后立即包含它

JSON = JSON || ;

JSON.stringify = function(value)  return value.toJSON(); ;

JSON.parse = JSON.parse || function(jsonsring)  return jsonsring.evalJSON(true); ;

这使得原型函数可以作为标准的 JSON.stringify() 和 JSON.parse() 使用,但如果可用,则保留本机 JSON.parse(),因此这使得它与旧浏览器更兼容。

【讨论】:

如果传入的“值”是对象,则 JSON.stringify 版本不起作用。你应该这样做: JSON.stringify = function(value) return Object.toJSON(value); ;【参考方案6】:

我对 Prototype 不太熟悉,但我在它的 docs 中看到了这一点:

Object.toJSON("a":[1,2])

不过,我不确定这是否会出现与当前编码相同的问题。

还有一个较长的tutorial 关于将 JSON 与 Prototype 结合使用。

【讨论】:

【参考方案7】:

这是我用于同一问题的代码:

function stringify(object)
      var Prototype = window.Prototype
      if (Prototype && Prototype.Version < '1.7' &&
          Array.prototype.toJSON && Object.toJSON)
              return Object.toJSON(object)
      
      return JSON.stringify(object)

您检查 Prototype 是否存在,然后检查版本。如果旧版本在所有其他情况下使用 Object.toJSON(如果已定义)则回退到 JSON.stringify()

【讨论】:

【参考方案8】:

这就是我的处理方式。

var methodCallString =  Object.toJSON? Object.toJSON(options.jsonMethodCall) :  JSON.stringify(options.jsonMethodCall);

【讨论】:

【参考方案9】:

我的宽容解决方案检查 Array.prototype.toJSON 是否对 JSON 字符串化有害,并在可能的情况下保留它,让周围的代码按预期工作:

var dummy =  data: [hello: 'world'] , test = ;

if(Array.prototype.toJSON) 
    try 
        test = JSON.parse(JSON.stringify(dummy));
        if(!test || dummy.data !== test.data) 
            delete Array.prototype.toJSON;
        
     catch(e) 
        // there only hope
    

【讨论】:

【参考方案10】:

正如人们所指出的,这是由于 Prototype.js - 特别是 1.7 之前的版本。我也遇到过类似的情况,但无论 Prototype.js 是否存在,我都必须有代码运行;这意味着我不能只删除 Array.prototype.toJSON,因为我不确定它依赖于什么。对于这种情况,这是我想出的最佳解决方案:

function safeToJSON(item) 
    if ([1,2,3] === JSON.parse(JSON.stringify([1,2,3])))
        return JSON.stringify(item); //sane behavior
     else  
        return item.toJSON(); // Prototype.js nonsense
    

希望它对某人有所帮助。

【讨论】:

【参考方案11】:

如果你不想杀死所有东西,并且有一个在大多数浏览器上都可以使用的代码,你可以这样做:

(function (undefined)  // This is just to limit _json_stringify to this scope and to redefine undefined in case it was
  if (true ||typeof (Prototype) !== 'undefined') 
    // First, ensure we can access the prototype of an object.
    // See http://***.com/questions/7662147/how-to-access-object-prototype-in-javascript
    if(typeof (Object.getPrototypeOf) === 'undefined') 
      if(().__proto__ === Object.prototype && ([]).__proto__ === Array.prototype) 
        Object.getPrototypeOf = function getPrototypeOf (object) 
          return object.__proto__;
        ;
       else 
        Object.getPrototypeOf = function getPrototypeOf (object) 
          // May break if the constructor has been changed or removed
          return object.constructor ? object.constructor.prototype : undefined;
        
      
    

    var _json_stringify = JSON.stringify; // We save the actual JSON.stringify
    JSON.stringify = function stringify (obj) 
      var obj_prototype = Object.getPrototypeOf(obj),
          old_json = obj_prototype.toJSON, // We save the toJSON of the object
          res = null;
      if (old_json)  // If toJSON exists on the object
        obj_prototype.toJSON = undefined;
      
      res = _json_stringify.apply(this, arguments);
      if (old_json)
        obj_prototype.toJSON = old_json;
      return res;
    ;
  
.call(this));

这看起来很复杂,但这仅在处理大多数用例时才复杂。 主要思想是覆盖JSON.stringify,从作为参数传递的对象中删除toJSON,然后调用旧的JSON.stringify,最后恢复它。

【讨论】:

data-* 属性中的 encodeURIComponent() 与 JSON.stringify()

】data-*属性中的encodeURIComponent()与JSON.stringify()【英文标题】:encodeURIComponent()vsJSON.stringify()indata-*attribute【发布时间】:2014-10-1004:39:07【问题描述】:我想使用数组作为data-*属性,并且很多***答案建议我应该使用JSON.stringify();Howt... 查看详情

如何 JSON.stringify 对象数组

】如何JSON.stringify对象数组【英文标题】:HowtoJSON.stringifyanarrayofobjects【发布时间】:2016-05-0700:44:08【问题描述】:我正在尝试JSON.stringify()以下键/值对,其中值是对象数组。varstring=JSON.stringify(onlineUsers:getUsersInRoom(users,room));这是... 查看详情

json.parse()与json.stringify()的区别

JSON.parse()与JSON.stringify()的区别JSON.parse()【从一个字符串中解析出json对象】例子://定义一个字符串vardata=‘{"name":"goatling"}‘//解析对象??JSON.parse(data)结果是:?name:"goatling"JSON.stringify()【从一个对象中解析出字符串】vardata={name:‘go... 查看详情

json对象与字符串的相互转换,数组和字符串的转换

1.json对象转换为字符串JSON.stringify(value[,replacer][,space]) varstudent=newObject();student.id="001";student.name="程陈";student.age="18";varstr=JSON.stringify(student);//{"id":"001","name":"程陈","age":"1 查看详情

json.parse()与json.stringify()的区别

...tling"}‘//解析对象??JSON.parse(data)结果是:?name:"goatling"JSON.stringify()【从一个对象中解析出字符串】vardata={name:‘goatling‘}JSON.stringify(data)结果是:‘{"nam 查看详情

如何 JSON.stringify 嵌套的对象数组 [关闭]

】如何JSON.stringify嵌套的对象数组[关闭]【英文标题】:HowtoJSON.stringifyannestedarrayofobjects[closed]【发布时间】:2020-07-1907:12:57【问题描述】:这是我的数据,data="SeatingArrangement":["data":["id":1,"rowName":"a","seatNo":0,"id":2,"rowName":"a","seatNo": 查看详情

json.stringify

JSON.stringify(value[,replacer][,space]) value:是必选字段。就是你输入的对象,比如数组,类等。 replacer:这个是可选的。它又分为2种方式,一种是数组,第二种是方法。   情况一:replacer为数组时,通过后面的实验可以... 查看详情

json.parse()与json.stringify()

JSON.parse()方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象。提供可选的reviver函数用以在返回之前对所得到的对象执行变换(操作)。语法JSON.parse(text[,reviver])参数text要被解析成JavaScript值的字符串,查看JSON对象学习... 查看详情

js解析与序列化json数据(一)json.stringify()的基本用法

...进行了规范,定义了全局对象JSON。JSON对象有两个方法:stringify()和parse()。在最简单的情况下,这两个方法分别用于把JavaScript对象序列化为JSON字符串和把JSON字符串解析为原生JavaScript。例如:新建一个HTML:代码如下:复制代码... 查看详情

js数组转换成json串(json.stringify)

例如:var giftlist[1490011777]=[];giftlist[1490011777][‘id‘]= 1490011777;giftlist[1490011777][‘name‘]= "礼包测试";giftlist[1490011777][‘desc‘]= "详情"; 转换json串varjsonStr=JSON.stringify 查看详情

json.stringify()的使用

参考技术A复制粘贴一下JSON.stringify()三个参数的含义:返回值:返回包含JSON文本的字符串。从上面的参数说明中可以看到,第二个参数可以是一个函数或者数组,这给了我们很大的发挥空间。stringify()的第一个和第三个参数都好... 查看详情

如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]

】如何在不使用JSON.stringify或JSON.parse的情况下在javascript中克隆数组?[复制]【英文标题】:HowtocloneanarrayinjavascriptwithoutusingJSON.stringifyorJSON.parse?[duplicate]【发布时间】:2014-11-0521:10:30【问题描述】:我有一个数组示例fruit。我想将... 查看详情

json.stringify详解

参考技术A当我们使用JSON.stringify()序列化一个值为JSON字符串,只有JSON安全的值才可以通过JSON.stringify()转换为字符串。那么,什么是JSON安全的值?能够有效用JSON形式表示的任何值。非JSON安全的值,例如:undefined、function和symbol... 查看详情

010天json.stringify()详解(代码片段)

JSON.stringify()除了要序列化的js对象外,还可以接受另外两个参数,这两个参数用于指定以不同的方式序列化js对象。第一个参数是个过滤器,可以是一个数组,也可以是一个函数;第二个参数是一个选项,表示是否在JSON字符串中... 查看详情

js中json.stringify()方法,将js对象转换成字符串,传入服务器

...在向服务器发送数据时一般是字符串。我们可以使用JSON.stringify()方法将JavaScript对象转换为字符串。语法JSON.stringify(value[,replacer[,space]])参数说明:value:必需,要转换的JavaScript值(通常为对象或数组)。replacer:可选。用于转换结... 查看详情

JSON.stringify 和 JSON.parse 之间的区别

】JSON.stringify和JSON.parse之间的区别【英文标题】:DifferencebetweenJSON.stringifyandJSON.parse【发布时间】:2013-07-2101:42:07【问题描述】:我一直对何时使用这两种解析方法感到困惑。在我回显我的json_encoded数据并通过ajax将其取回后,我... 查看详情

json.parse()与json.stringify()

...每个属性名都必须用双引号,否则会抛出异常。 JSON.stringify将JSON对象转换为字符串vara={a:1,b:2}JSON.s 查看详情

与 javascript 日期相比,Json Stringify 日期产生错误的日​​期

】与javascript日期相比,JsonStringify日期产生错误的日​​期【英文标题】:JsonStringifydateproducesawrongdatecomparedtojavascriptdate【发布时间】:2017-01-0223:01:04【问题描述】:当我创建一个javascript日期然后stringify并将其发送到服务器时,... 查看详情