类型化对象的Javascript序列化
我不清楚序列化/反序列化应该如何在JavaScript中的类型化对象上工作。例如,我有一个包含各种成员和数组的“MapLayer”对象。我已编写(但尚未测试)以下代码以尝试对其进行序列化:类型化对象的Javascript序列化,javascript,json,serialization,Javascript,Json,Serialization,我不清楚序列化/反序列化应该如何在JavaScript中的类型化对象上工作。例如,我有一个包含各种成员和数组的“MapLayer”对象。我已编写(但尚未测试)以下代码以尝试对其进行序列化: MapLayer.prototype.serialize = function() { var result = "{tileset:tilesets." + tilesets.getTilesetName(this.tileset) + ",columns:" + this.columns + ",r
MapLayer.prototype.serialize = function() {
var result = "{tileset:tilesets." + tilesets.getTilesetName(this.tileset) + ",columns:" + this.columns + ",rows:" + this.rows +
",offsetX:" + this.offsetX + ",offsetY:" + this.offsetY + ",currentX:" + this.currentX + ",currentY:" + this.currentY +
",scrollRateX:" + this.scrollRateX + ",scrollRateY:" + this.scrollRateY + ",virtualColumns:" + this.virtualColumns + ",virtualRows:" + this.virtualRows +
",tiles:\"" + this.encodeTileData2() + "\"";
for(key in this)
{
if(this[key] instanceof Sprite)
result += "," + key + ":" + this[key].serialize();
}
return result;
}
我的问题是,如何将结果对象反序列化为MapLayer对象而不是通用对象。以及如何将所有精灵实例反序列化为精灵。我应该使用“new MapLayer()”而不是“{}”吗?或者我只是想在序列化中包含对象的原型和构造函数属性?我还缺什么?我这样做是不是很愚蠢?我不使用泛型序列化/反序列化代码有两个原因:
function MapLayer(map, tileset, columns, rows, virtualColumns, virtualRows, offsetX, offsetY, scrollRateX, scrollRateY, priority, tileData) {
this.map = map;
this.tileset = tileset;
this.columns = columns;
this.rows = rows;
this.offsetX = offsetX;
this.offsetY = offsetY;
this.currentX = offsetX;
this.currentY = offsetY;
this.scrollRateX = scrollRateX;
this.scrollRateY = scrollRateY;
if(tileData.length < columns * rows * 2)
this.tiles = DecodeData1(tileData);
else
this.tiles = DecodeData2(tileData);
this.virtualColumns = virtualColumns ? virtualColumns : columns;
this.virtualRows = virtualRows ? virtualRows : rows;
}
现在的问题是如何最好地合并这些依赖对象,因为JSON再次丢失了对象的“类型”(原型?)。与其运行构造函数,不如简单地更改serialize和de-serialize函数,以确保对象只需要像这样构造一次,而不需要创建和复制
Person.prototype.serialize = function () {
var obj = this;
return '({ ' + Object.getOwnPropertyNames( this ).map( function ( key ) {
var value = obj[key];
if ( typeof value === 'string' ) { value = '"' + value + '"'; }
return key + ': ' + value;
}).join( ', ' ) + ',"__proto__":Person.prototype})';
};
Person.deserialize = function ( input ) {
return eval( input );
};
编辑3:
我遇到的另一个问题是JSON在IE9中似乎不起作用。我正在使用此测试文件:
<html>
<head>
<title>Script test</title>
<script language="javascript">
console.log(JSON);
</script>
</head>
</html>
编辑4:
要更正JSON问题,我必须在开头包含正确的DOCTYPE标记。首先,这里是一个自定义序列化/反序列化的简单示例:
function Person( name, sex, age ) {
this.name = name;
this.sex = sex;
this.age = age;
}
Person.prototype.serialize = function () {
var obj = this;
return '{ ' + Object.getOwnPropertyNames( this ).map( function ( key ) {
var value = obj[key];
if ( typeof value === 'string' ) { value = '"' + value + '"'; }
return '"' + key + '": ' + value;
}).join( ', ' ) + ' }';
};
Person.deserialize = function ( input ) {
var obj = JSON.parse( input );
return new Person( obj.name, obj.sex, obj.age );
};
用法:
首先,我们创建一个新的实例对象:
var person = new Person( 'John', 'male', 25 );
现在,我们使用Person.prototype.serialize
方法将该对象序列化为字符串:
var string = person.serialize();
这将使用以下字符串:
{ "name": "John", "sex": "male", "age": 25 }
最后,我们使用Person.deserialize
static方法反序列化该字符串:
var person2 = Person.deserialize( string );
现在,person2
是Person
的一个实例,它包含与原始Person
实例相同的属性值
现场演示:
现在,尽管在任何情况下都需要
Person.deserialize
静态方法(它在内部使用JSON.parse
,并调用Person
构造函数初始化新实例),但另一方面,Person.prototype.serialize
方法,仅当内置的JSON.stringify
静态方法不能满足要求时才需要
在我上面的示例中,var string=JSON.stringify(person)
也可以完成这项工作,因此不需要自定义序列化机制。请参见此处:但是,您的案例更复杂,因此您需要定义一个自定义序列化函数。如果您查看ST-JS()项目,它允许在服务器端用Java创建对象图,在JSON中序列化,并在客户端(Javascript)以类型化方式反序列化,也就是说,对象将使用其构造函数实例化,您可以对创建的对象调用方法
要使用ST-JS,您应该使用Java编写您的客户机代码,这在Javascript中几乎是一对一的转换
网站主页上的AJAX/JSON一章解释了如何在保留类型信息的同时解析JSON字符串。使用构造函数而不是“object”的对象。我不知道该怎么称呼它。啊,你指的是属于你自己的构造函数的对象(
MapLayer
,Sprite
,等等)…我的建议是一个MapLayer.prototype.deserialize
方法,它将接受一个字符串并返回一个MapLayer
对象。我正在处理一个示例…那么在本例中请避免使用JSON?由JSON.stringify(yourMapLayerObj)
返回的字符串是否符合您的要求?如果没有,那么您显然需要一个定制的stringify/parse解决方案……我已经更新了这个问题。为什么我们不设置\uuuuu proto\uuuu
而不是调用构造函数呢?另一个问题是,如果我尝试在IE中使用JSON,我会得到一个错误“JSON未定义”。@BlueMonkMN因为\uuu proto\uuu
是非标准的,不推荐使用。它从未在IE中实现过(将来也不会)。ECMAScript标准不提供任何方法来设置对象的原型链接。。。你正在使用哪个版本的IE?JSON
对象是在IE8中添加的…@BlueMonkMN在IE中尝试console.log(JSON)
。您应该在IE的控制台(F12->console选项卡)中获得'[object JSON]
。@BlueMonkMN啊,这是因为您没有定义doctype。添加
作为HTML文档的第一行。如果你不能定义一个有效的doctype,IE会进入怪癖模式…我想OP是在询问现有代码库使用的技术,而不是迁移到另一个框架。是的,你说得对。我指出的问题是,为了能够以通用方式反序列化“类型化”对象的图形(如编辑2中),您需要以某种方式存储有关“类型化对象”的元数据,即告诉反序列化器,“Person”的“devices”属性就是“Device”数组.如果你看一下我们的parseJSON函数(应该可以很容易地提取),它使用一个名为“typeDescription”的“静态”字段,这是一个简单的映射-我们的框架生成,但也可以手动创建。
{ "name": "John", "sex": "male", "age": 25 }
var person2 = Person.deserialize( string );