Javascript序列化的类型对象

Blu*_*kMN 8 javascript serialization json

我不清楚序列化/反序列化应该如何处理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;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何将结果对象作为MapLayer对象而不是通用对象进行反序列化.如何将所有Sprite实例作为精灵进行反序列化.我应该使用"new MapLayer()"而不是"{}"吗?或者我只是想在序列化中包含对象的原型和构造函数属性?还有什么我想念的吗?我这样做是一种愚蠢的方式吗?我没有使用通用序列化/反序列化代码有两个原因:

  1. 我想以优化的格式序列化tile数据,而不是为每个tile存储一个base-10字符串表示,并用逗号分隔它们.
  2. 我不想将tileset序列化为在反序列化期间构造为新对象的对象,而是将其作为对现有对象的引用.是否可以使用我上面提到的代码?

编辑: 请原谅我缺乏适当的术语; 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;
}
Run Code Online (Sandbox Code Playgroud)

编辑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 );
Run Code Online (Sandbox Code Playgroud)

现在的问题是如何最好地合并这些依赖对象,因为再一次,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 );
};
Run Code Online (Sandbox Code Playgroud)

编辑3: 我遇到的另一个问题是JSON似乎在IE9中不起作用.我正在使用这个测试文件:

<html>
<head>
<title>Script test</title>
<script language="javascript">
console.log(JSON);
</script>
</head>
</html>
Run Code Online (Sandbox Code Playgroud)

控制台输出:

SCRIPT5009: 'JSON' is undefined 
test.html, line 5 character 1
Run Code Online (Sandbox Code Playgroud)

编辑4: 要纠正JSON问题,我必须在开头包含正确的DOCTYPE标记.

Šim*_*das 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 );
};
Run Code Online (Sandbox Code Playgroud)

用法:

首先,我们创建一个新的实例对象:

var person = new Person( 'John', 'male', 25 );
Run Code Online (Sandbox Code Playgroud)

现在,我们使用以下Person.prototype.serialize方法将该对象序列化为字符串:

var string = person.serialize();
Run Code Online (Sandbox Code Playgroud)

这将使用此字符串:

{ "name": "John", "sex": "male", "age": 25 }
Run Code Online (Sandbox Code Playgroud)

最后,我们使用Person.deserialize静态方法反序列化该字符串:

var person2 = Person.deserialize( string );
Run Code Online (Sandbox Code Playgroud)

现在,person2是一个实例,Person并包含与原始person实例相同的属性值.

现场演示: http ://jsfiddle.net/VMqQN/


现在,虽然Person.deserialize在任何情况下都需要静态方法(它在JSON.parse内部使用,并调用Person构造函数来初始化一个新实例),但Person.prototype.serialize另一方面,只有在内置JSON.stringify静态方法不够时才需要该方法.

在上面的示例中,var string = JSON.stringify( person )也可以完成工作,因此不需要自定义序列化机制.请参阅此处:http://jsfiddle.net/VMqQN/1/但是,您的情况更复杂,因此您需要定义自定义序列化功能.