Javascript序列化的类型对象 [英] Javascript Serialization of Typed Objects

查看:107
本文介绍了Javascript序列化的类型对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不清楚序列化/反序列化应该如何处理JavaScript中的类型化对象。例如,我有一个包含各种成员和数组的MapLayer对象。我已经编写(但尚未测试)以下代码来尝试序列化它:

I'm unclear how serialization/de-serialization is supposed to work on typed objects in JavaScript. For example, I have a "MapLayer" object that contains various members and arrays. I have written (but not yet tested) the following code to attempt to serialize it:

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()而不是{}吗?或者我只是想在序列化中包含对象的原型和构造函数属性?还有什么我想念的吗?我这样做是一种愚蠢的方式吗?我没有使用通用序列化/反序列化代码有两个原因:

My question is, how is the resulting object supposed to get deserialized as a MapLayer object rather than as a generic Object. And how are all the Sprite instances supposed to get deserialized as sprites. Should I be using "new MapLayer()" instead of "{}"? Or am I simply supposed to include the prototype and constructor properties of the object in the serialization? Anything else I'm missing? Am I doing this a stupid way? There are 2 reasons I'm not using generic serialization/de-serialization code:


  1. 我想以优化格式序列化切片数据而不是为每个磁贴存储一个基数为10的字符串表示,并用逗号分隔它们。

  2. 我不想将tileset序列化为一个被构造为新的对象反序列化期间的对象,而不是对现有对象的引用。是否可以使用我上面提到的代码?

编辑:请原谅我缺乏适当的术语; JavaScript是我不那么专业的语言之一。当我说Typed Object是一个带有构造函数的对象时,我的意思是什么。在这个例子中,我的构造函数是:

Excuse my lack of proper terminology; JavaScript is one of my less expert languages. What I mean when I said "Typed Object" is an object with a constructor. In this example, my constructor is:

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的相关对象:

Edit 2: Taking the code from Šime Vidas' answer, I have added a related object called "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丢失了。而不是运行构造函数,为什么我们不简单地更改序列化和反序列化函数以确保对象只需要像这样构造一次而不是创建和复制?

Now the question is how best to incorporate such dependent objects, because once again, the "type" (prototype?) of the object gets lost by JSON. Instead of running the constructor, why don't we simply change the serialize and the de-serialize functions to ensure that the object only needs to be constructed once like this instead of created and copied?

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中不起作用。我正在使用此测试文件:

Edit 3: Another problem I have is that JSON doesn't seem to work in IE9. I'm using this test file:

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

Edit 4: To correct the JSON problem I must include the correct DOCTYPE tag at the beginning.

推荐答案

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

For a start, here is a simple example of custom serialization / deserialization:

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

用法:

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

First, we create a new instance object:

var person = new Person( 'John', 'male', 25 );

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

var string = person.serialize();

这将使用此字符串:

{ "name": "John", "sex": "male", "age": 25 }

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

Finally, we deserialize that string using the Person.deserialize static method:

var person2 = Person.deserialize( string );

现在, person2 是<的实例code> Person 并包含与原始 person 实例相同的属性值。

Now, person2 is an instance of Person and contains the same property values as the original person instance.

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

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

Now, while the Person.deserialize static method is required in any case (it uses JSON.parse internally, and invokes the Person constructor to initialize a new instance), the Person.prototype.serialize method on the other hand, is only needed if the built-in JSON.stringify static method doesn't suffice.

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

In my example above var string = JSON.stringify( person ) would get the job done too, so a custom serialization mechanism is not needed. See here: http://jsfiddle.net/VMqQN/1/ However, your case is more complex, so you'll need to define a custom serialization function.

这篇关于Javascript序列化的类型对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆