我不清楚序列化/反序列化应该如何处理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实例作为精灵进行反序列化。我应该使用“new MapLayer()”而不是“{}”吗?或者我只是想在序列化中包含对象的原型和构造函数属性?还有什么我想念的吗?我这样做是一种愚蠢的方式吗?我没有使用通用序列化/反序列化代码有两个原因:
编辑:请原谅我缺乏适当的术语; JavaScript是我不那么专业的语言之一。当我说“Typed Object”是一个带有构造函数的对象时,我的意思是什么。在这个例子中,我的构造函数是:
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丢失。我们为什么不简单地更改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>
控制台输出:
SCRIPT5009: 'JSON' is undefined
test.html, line 5 character 1
编辑4: 要纠正JSON问题,我必须在开头包含正确的DOCTYPE标记。
答案 0 :(得分:8)
首先,这是一个自定义序列化/反序列化的简单示例:
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
静态方法反序列化该字符串:
var person2 = Person.deserialize( string );
现在,person2
是Person
的一个实例,包含与原始person
实例相同的属性值。
现场演示: http://jsfiddle.net/VMqQN/
现在,虽然在任何情况下都需要Person.deserialize
静态方法(它在内部使用JSON.parse
,并调用Person
构造函数来初始化新实例),{{1}另一方面,只有在内置Person.prototype.serialize
静态方法不够的情况下才需要使用方法。
在上面的示例中,JSON.stringify
也可以完成工作,因此不需要自定义序列化机制。请参阅此处:http://jsfiddle.net/VMqQN/1/但是,您的情况更复杂,因此您需要定义自定义序列化功能。
答案 1 :(得分:1)
如果你看一下ST-JS(http://st-js.org)项目,它允许在服务器端用Java创建你的对象图,用JSON序列化它,然后在客户端(Javascript)反序列化它。一种类型化的方式,即对象将使用它们的构造函数进行实例化,您可以在创建的对象上调用方法。
要使用ST-JS,您应该编写您的客户端代码是Java,在Javascript中几乎一对一转换。
网站主页上的AJAX / JSON章节向您解释如何在保留类型信息的同时解析JSON字符串。