Javascript:stringify对象(包括类型函数的成员)

时间:2010-09-10 15:01:11

标签: javascript json function serialization stringify

我正在寻找一种解决方案,将Javascript对象序列化(和反序列化)到跨浏览器的字符串,包括碰巧是函数的对象的成员。典型的对象如下所示:

{
   color: 'red',
   doSomething: function (arg) {
        alert('Do someting called with ' + arg);
   }
}

doSomething()只包含局部变量(不需要序列化调用上下文!)。

JSON.stringify()将忽略'doSomething'成员,因为它是一个函数。我知道toSource()方法会做我想要的,但它是特定于FF的。

5 个答案:

答案 0 :(得分:8)

您可以将JSON.stringifyreplacer类似使用:

JSON.stringify({
   color: 'red',
   doSomething: function (arg) {
        alert('Do someting called with ' + arg);
   }
}, function(key, val) {
        return (typeof val === 'function') ? '' + val : val;
});

答案 1 :(得分:6)

快速而肮脏的方式是这样的:

Object.prototype.toJSON = function() {
  var sobj = {}, i;
  for (i in this) 
    if (this.hasOwnProperty(i))
      sobj[i] = typeof this[i] == 'function' ?
        this[i].toString() : this[i];

 return sobj;

};

显然这会影响代码中每个对象的序列化,并且可能会使用未经过滤的for in循环来绊倒niave代码。 “正确”的方法是编写一个递归函数,在任何给定对象的所有后代成员上添加toJSON函数,处理循环引用等。但是,假设单线程Javascript(没有Web Workers),此方法应该可以工作,不会产生任何意外的副作用。

必须在Array的原型中添加类似的函数,以通过返回数组而不是对象来覆盖Object。另一个选择是附加一个单独的选项,让它根据对象自身的性质选择性地返回一个数组或一个对象,但它可能会更慢。

function JSONstringifyWithFuncs(obj) {
  Object.prototype.toJSON = function() {
    var sobj = {}, i;
    for (i in this) 
      if (this.hasOwnProperty(i))
        sobj[i] = typeof this[i] == 'function' ?
          this[i].toString() : this[i];

    return sobj;
  };
  Array.prototype.toJSON = function() {
      var sarr = [], i;
      for (i = 0 ; i < this.length; i++) 
          sarr.push(typeof this[i] == 'function' ? this[i].toString() : this[i]);

      return sarr;
  };

  var str = JSON.stringify(obj);

  delete Object.prototype.toJSON;
  delete Array.prototype.toJSON;

  return str;
}

http://jsbin.com/yerumateno/2/edit

答案 2 :(得分:1)

像这样......

(function(o) {
    var s = "";
    for (var x in o) {
        s += x + ": " + o[x] + "\n";
    }
    return s;
})(obj)

注意:这是一个表达式。它返回作为参数传入的对象的字符串表示形式(在我的示例中,我将传入名为obj的变量)。

您还可以覆盖Object原型的toString方法:

Object.prototype.toString = function() {
    // define what string you want to return when toString is called on objects
}

答案 3 :(得分:1)

没有物体本身的帮助是不可能的。例如,您如何序列化此表达式的结果?

(function () {
  var x; 
  return {
      get: function () { return x; },
      set: function (y) { return x = y; }
    };
})();

如果您只是获取函数的文本,那么当您反序列化时,x将引用全局变量,而不是闭包中的变量。此外,如果您的函数关闭浏览器状态(比如对div的引用),您必须考虑您想要的含义。

当然,您可以编写自己的特定于各个对象的方法,这些方法编码您希望引用其他对象的语义。

答案 4 :(得分:1)

JSONfn插件正是您所需要的。

http://www.eslinstructor.net/jsonfn/

- 瓦迪姆