我不清楚序列化/反序列化应该如何在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实例反序列化为sprite。我应该使用“ new MapLayer()”而不是“ {}”吗?还是我只是应该在序列化中包括对象的原型和构造函数属性?我还有什么想念的吗?我这样做是不是很愚蠢?我不使用通用序列化/反序列化代码有两个原因:
编辑: 对不起,我缺乏适当的术语;JavaScript是我的专业语言之一。当我说“类型化对象”时,我的意思是带有构造函数的对象。在此示例中,我的构造函数是:
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: 从ŠimeVidas的答案中获得代码,我添加了一个名为“ 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标记。
首先,这是自定义序列化/反序列化的简单示例:
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方法将该对象序列化为字符串:
Person.prototype.serialize
var string = person.serialize();
这将使用以下字符串:
{ "name": "John", "sex": "male", "age": 25 }
最后,我们使用Person.deserialize静态方法反序列化该字符串:
Person.deserialize
var person2 = Person.deserialize( string );
现在,person2是的实例,Person并且包含与原始person实例相同的属性值。
person2
Person
person
现场演示: http : //jsfiddle.net/VMqQN/
现在,尽管Person.deserialize在任何情况下都需要静态方法(它在JSON.parse内部使用,并调用Person构造方法以初始化新实例),但Person.prototype.serialize另一方面,仅在内置JSON.stringify静态方法不足时才需要该方法。
JSON.parse
JSON.stringify
在我上面的示例中,var string = JSON.stringify( person )也可以完成这项工作,因此不需要自定义序列化机制。请参阅此处:http : //jsfiddle.net/VMqQN/1/但是,您的情况更为复杂,因此需要定义一个自定义序列化函数。
var string = JSON.stringify( person )