字符串化 JSON 内部对象的最佳实践

Best practices for stringifying JSON inner objects

基本上我有这样的东西:

MyClass

var MyClass = function() {
  this.num = 123;
  this.obj = new MyInnerClass();
};

MyClass.prototype.stringify = function() {
  return JSON.stringify(this);
};

MyInnerClass

var MyInnerClass = function() {
  this.foo = 456;
  this.bar = 'bonjour!';
};

MyInnerClass.prototype.stringify = function() {
  return JSON.stringify(this, function(k, v) {
    // ignores 'foo' attribute
    return k !== 'foo' ? v : undefined;
  });
};

每个 class 都有自己的 stringify 实现,所以当我这样做时:

var mc = new MyClass();
mc.stringify();

我希望调用 MyClass.stringify 应该将我的 mc 对象字符串化,但尊重内部对象 stringify 实现。一旦我们无法控制 JSON.stringify 方法逻辑,是否有 好的 方法来做到这一点?

谢谢!

如果您在 JSON.stringify 上查看 MDN,您会看到一个讨论 toJSON 属性[= 的部分18=]

If an object being stringified has a property named toJSON whose value is a function, then the toJSON() method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON() method when called will be serialized.

基本上,为您的 Object 定义一个 toJSON 方法,它创建另一个 Object,但可以根据需要进行序列化。然后 JSON.stringify 将序列化 toJSON 函数的 return,即

var MyClass = function() {
  this.num = 123;
  this.obj = new MyInnerClass();
};

var MyInnerClass = function() {
  this.foo = 456;
  this.bar = 'bonjour!';
};

MyInnerClass.prototype.toJSON = function () {
    // shallow clone `this`, except .foo
    var o = Object.create(null), k, blacklist = ['foo'];
    for (k in this) // loop over enumerable properties
        if (Object.prototype.hasOwnProperty.call(this, k)) // ignore inherited properties
            if (blacklist.indexOf(k) === -1) // ignore blacklisted properties
                o[k] = this[k]; // add to our clone
    return o;
};

JSON.stringify(new MyClass()); // '{"num":123,"obj":{"bar":"bonjour!"}}'

这也将取代您对当前 stringify 方法的需要。


遗憾的是,您不能在 .toJSON 内调用 JSON.stringify(this),因为它变成了循环,您会得到 RangeError: Maximum call stack size exceeded,但无论如何您都无法通过这种方式获得所需的结果第二次被序列化,在你的 JSON.

中给你一个 String