一尘不染

类型对象的Javascript序列化

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;
}

我的问题是,如何将生成的对象反序列化为MapLayer对象而不是通用对象。以及如何将所有Sprite实例反序列化为sprite。我应该使用“ new
MapLayer()”而不是“
{}”吗?还是我只是应该在序列化中包括对象的原型和构造函数属性?我还有什么想念的吗?我这样做是不是很愚蠢?我不使用通用序列化/反序列化代码有两个原因:

  1. 我想以一种优化的格式序列化图块数据,而不是为每个图块存储以10为底的字符串表示形式,并用逗号分隔它们。
  2. 我不想将tileset序列化为在反序列化期间被构造为新对象的对象,而只是对现有对象的引用。使用上面我建议的代码是否可行?

编辑:
对不起,我缺乏适当的术语;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 );

现在的问题是如何最好地合并此类依赖对象,因为该对象的“类型”(原型?)再次被JS​​ON丢失了。为什么不简单地更改序列化和反序列化函数,以确保只需要像这样构造一次对象,而不是创建和复制它,而不是运行构造函数?

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标记。


阅读 234

收藏
2020-07-27

共1个答案

一尘不染

首先,这是自定义序列化/反序列化的简单示例:

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构造方法以初始化新实例),但Person.prototype.serialize另一方面,仅在内置JSON.stringify静态方法不足时才需要该方法。

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

2020-07-27