Frage

Basically, socket.io uses nativeJSON to enconde and decode packets, and my problem is that I am obliged to use this version of prototype which changes JSON behaviour. When I should get in the server something like:

socket.on('event', function (a, b, c), I get socket.on('event', function ([a, b, c], undefined, undefined).

One solution is to comment this lines on json.js:

/* socket.io-client/lib/json.js
if (nativeJSON && nativeJSON.parse){
    return exports.JSON = {
      parse: nativeJSON.parse
    , stringify: nativeJSON.stringify
    };
  }
*/

but this change affects performance seriously.

Is there a way to recover native JSON functionality? Would it be possible to create a hidden iframe just to clone the JSON object to restore the old functionality?

War es hilfreich?

Lösung

One solution is to kill Prototype's toJSON() extension methods:

if(window.Prototype) {
    delete Object.prototype.toJSON;
    delete Array.prototype.toJSON;
    delete Hash.prototype.toJSON;
    delete String.prototype.toJSON;
}

Then you should be able to use the browser's native JSON.parse/stringify methods without issue.

Andere Tipps

If you don't want to kill everything, and have a code that would be okay on most browsers, you could do it this way :

(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://stackoverflow.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));

This seems complex, but this is complex only to handle most use cases. The main idea is overriding JSON.stringify to remove toJSON from the object passed as an argument, then call the old JSON.stringify, and finally restore it.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top