我不太清楚在JavaScript中如何对类型化对象进行序列化/反序列化。例如,我有一个包含各种成员和数组的“MapLayer”对象。我已经编写了以下代码(但尚未测试)来尝试将其序列化:
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对象进行反序列化,而不是作为通用对象进行反序列化。所有Sprite实例应该如何被反序列化为sprites。我应该使用“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;
}
编辑2:从Šime Vidas的回答中获取代码后,我添加了一个名为“Device”的相关对象:
function Device( description, memory ) {
this.description = description;
this.memory = memory;
}
function Person( name, sex, age, devices ) {
this.name = name;
this.sex = sex;
this.age = age;
this.devices = devices;
}
Person.deserialize = function ( input ) {
var obj = JSON.parse( input );
return new Person( obj.name, obj.sex, obj.age, obj.devices );
};
var device = new Device( 'Blackberry', 64);
var device2 = new Device( 'Playstation 3', 600000);
var person = new Person( 'John', 'male', 25, [device, device2] );
var string = JSON.stringify(person);
console.log( string );
var person2 = Person.deserialize( string );
console.log( person2 );
console.log( person2 instanceof Person );
现在的问题是如何最好地整合这些依赖对象,因为再次提醒,JSON会丢失对象的“类型”(原型?)。 与其运行构造函数,为什么不改变序列化和反序列化函数以确保对象只需要像这样构建一次,而不是创建并复制?
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>
控制台输出如下:
SCRIPT5009: 'JSON' is undefined
test.html, line 5 character 1
编辑4: 为了纠正JSON问题,我必须在开头包含正确的DOCTYPE标签。
MapLayer
、Sprite
等)…… - Šime VidasMapLayer.prototype.deserialize
方法,该方法将接受一个字符串并返回一个MapLayer
对象。我正在编写一个示例... - Šime VidasJSON.stringify(yourMapLayerObj)
返回的字符串是否符合您的要求?如果不符合,那么显然您需要一个自定义的 stringify/parse 解决方案... - Šime Vidas