您可以修改JSON结构以存储类型信息。如果您有大量对象需要进行序列化和反序列化,这将节省编写每个对象的自定义代码所需的时间。
另外,请注意,这会修改JSON结构并为每个自定义对象添加一个__type__属性。我认为这比保留单独的配置文件更清晰。因此,下面是它的基本工作原理:
var fruitBowl = {..};
fruitBowl[0].eat();
fruitBowl[1].seeds[0].plant();
调用对象上的serialize方法以获取JSON表示。
var json = fruitBowl.serialize();
调用deserialize方法对JSON编码的字符串进行反序列化,以重建对象。
var resurrected = json.deserialize()
现在您可以访问对象的属性并调用方法:
resurrected[0].eat();
resurrected[1].seeds[0].plant();
它适用于任何深度嵌套对象的级别,尽管它现在可能有一些错误。此外,它很可能不是跨浏览器的(仅在Chrome上进行了测试)。由于反序列化程序不熟悉对象的构造函数,因此它基本上创建每个自定义对象而不传递任何参数。我在jsfiddle上设置了一个工作演示,网址为:
http://jsfiddle.net/kSATj/1/。
构造函数必须修改以考虑其对象可以创建的两种方式:
1. 直接在Javascript中
2. 从JSON重建
所有构造函数都需要适应从两端创建,因此每个属性都需要分配默认回退值,以防未传递任何内容。
function SomeObject(a, b) {
this.a = a || false;
this.b = b || null;
}
var o = new SomeObject("hello", "world");
var o = new SomeObject();;
o.a = "hello";
o.b = "world";
作为参考,修改后的JSON如下:
{"fruitbowl":
[
{
"__type__": "Fruit",
"name": "apple",
"color": "red",
"seeds": []
},
{
"__type__": "Fruit",
"name": "orange",
"color": "orange",
"seeds":
[
{
"__type__": "Seed",
"size": "small",
"density": "hard"
},
{
"__type__": "Seed",
"size": "small",
"density": "soft"
}
]
}
]
}
这只是一个用于识别简单类型的辅助函数:
function isNative(object) {
if(object == null) {
return true;
}
var natives = [Boolean, Date, Number, String, Object, Function];
return natives.indexOf(object.constructor) !== -1;
}
将对象序列化为JSON(保留类型信息):
Object.prototype.serialize = function() {
var injectTypes = function(object) {
if(!isNative(object)) {
object.__type__ = object.constructor.name;
}
for(key in object) {
var property = object[key];
if(object.hasOwnProperty(key) && !isNative(property)) {
injectTypes(property);
}
}
};
var removeTypes = function(object) {
if(object.__type) {
delete object.__type__;
}
for(key in object) {
var property = object[key];
if(object.hasOwnProperty(key) && !isNative(property)) {
removeTypes(property);
}
}
}
injectTypes(this);
var json = JSON.stringify(this);
removeTypes(this);
return json;
};
反序列化(包括重构自定义对象):
String.prototype.deserialize = function() {
var rawObject = JSON.parse(this.toString());
var reconstruct = function(object) {
var reconstructed = {};
if(object.__type__) {
reconstructed = new window[object.__type__]();
delete object.__type__;
}
else if(isNative(object)) {
return object;
}
for(key in object) {
var property = object[key];
if(object.hasOwnProperty(key)) {
reconstructed[key] = reconstruct(property);
}
}
return reconstructed;
}
return reconstruct(rawObject);
};