如何将inheritance的对象string化为JSON?
当使用JSON.stringify()时,json2.js似乎忽略父对象的成员。 例:
require('./json2.js'); function WorldObject(type) { this.position = 4; } function Actor(val) { this.someVal = 50; } Actor.prototype = new WorldObject(); var a = new Actor(2); console.log(a.position); console.log(JSON.stringify(a));
输出是:
4 {"someVal":50}
我期望这个输出:
4 {"position":0, "someVal":50}
那么就是这样, JSON.stringify
不保留对象的任何非拥有的属性。 您可以在这里看看关于其他缺点和可能的解决方法的有趣讨论。
另外请注意,作者不仅logging了这些问题,还写了一个名为HydrateJS的库,可以帮助你。
这个问题比起初看起来要深一点。 即使a
真正的string到{"position":0, "someVal":50}
,然后parsing它将创build一个对象具有所需的属性,但既不是一个Actor的实例,也没有原型链接WorldObject(毕竟,parsing方法没有这个信息,所以它不可能以这种方式恢复)。
为了保持原型链,聪明的技巧是必要的(像HydrateJS中使用的那些)。 如果这不是你想要的,也许你只需要在对其进行string化之前将对象“变平”。 要做到这一点,你可以例如迭代对象的所有属性,而不pipe它们是否是自己的,并重新赋值(这将确保它们在对象本身上定义,而不是从原型inheritance)。
function flatten(obj) { var result = Object.create(obj); for(var key in result) { result[key] = result[key]; } return result; }
函数写入的方式不会改变原始对象。 所以使用
console.log(JSON.stringify(flatten(a)));
你会得到你想要的输出和a
将保持不变。
另一种select是在要序列化的对象原型中定义一个toJSON
方法:
function Test(){} Test.prototype = { someProperty: "some value", toJSON: function() { var tmp = {}; for(var key in this) { if(typeof this[key] !== 'function') tmp[key] = this[key]; } return tmp; } }; var t = new Test; JSON.stringify(t); // returns "{"someProperty" : "some value"}"
这是因为JSON.stringify在尝试本地序列化之前在它接收的对象中searchtoJSON
方法。
检查这个小提琴: http : //jsfiddle.net/AEGYG/
你可以使用这个函数平坦化对象:
function flatStringify(x) { for(var i in x) { if(!x.hasOwnProperty(i)) { // weird as it might seem, this actually does the trick! - adds parent property to self x[i] = x[i]; } } return JSON.stringify(x); }
尽pipe一般的flatten
方法是有效的,但迄今为止发布的其他答案中的片段对于不可修改的属性不起作用,例如如果原型已经被冻结 。 为了处理这种情况,你需要创build一个新的对象,并为这个新的对象分配属性。 既然你只是把结果对象串起来,对象标识和其他JavaScript内部可能并不重要,所以返回一个新的对象是完全正确的。 这种方法也可以说比将一个对象的属性重新分配给自己更可读,因为它看起来不像一个无操作:
function flatten(obj) { var ret = {}; for (var i in obj) { ret[i] = obj[i]; } return ret; }
这里是他的答案中包含的@TomasVana片段的recursion版本,以防在对象树的多个层次中存在inheritance:
var flatten = function(obj) { if (obj === null) { return null; } if (Array.isArray(obj)) { var newObj = []; for (var i = 0; i < obj.length; i++) { if (typeof obj[i] === 'object') { newObj.push(flatten(obj[i])); } else { newObj.push(obj[i]); } } return newObj; } var result = Object.create(obj); for(var key in result) { if (typeof result[key] === 'object') { result[key] = flatten(result[key]); } else { result[key] = result[key]; } } return result; }
它将数组保存为数组。 以同样的方式调用它:
console.log(JSON.stringify(flatten(visualDataViews)));