当前位置: 首页 > 面试题库 >

类型对象的Javascript序列化

方嘉志
2023-03-14
问题内容

我不清楚序列化/反序列化应该如何在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标记。


问题答案:

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

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/但是,您的情况更为复杂,因此需要定义一个自定义序列化函数。



 类似资料:
  • 我想通过Google Gson传输一个列表对象,但我不知道如何反序列化泛型类型。 我在看了这个之后尝试了什么(Balusc的回答): 编辑: 现在我有 但是,我确实在“FromJson”行得到以下异常: null

  • 我有一个看起来很常见的问题,但到目前为止,我还没有找到一个适合我的解决方案。我想我只是错过了一些小事情,但我已经崩溃了,请求帮助。我正在尝试使用flask和pymongo获得json输出。 以下是控制台中使用print(结果)的对象: 当我试图返回时,我得到了错误: TypeError: ObjectId类型的对象不是JSON可序列化的 类联系人(资源): 我试过bson。json_util建议。

  • 我认为最好用一个例子来解释。 我有一个想要反序列化的JSON对象,它包含一个接口类型列表以及列表中的类型,但是我不确定如何让反序列化器确定列表中的具体类型: 要反序列化的类型 界面 儿童 我知道如果类型不是<code>List</code>,我可以将类型与<code>JsonSubTypes</code>一起使用,例如: 如果在父类型内,也是如此。但是当类型在类之外时,是否有一种方法可以帮助反序列

  • 本文向大家介绍javascript之Boolean类型对象,包括了javascript之Boolean类型对象的使用技巧和注意事项,需要的朋友参考一下 Boolean对象和Java中的Boolean封装类很像,它有两个值:true和false 1、创建Boolean对象 2、Boolean对象的constructor属性是Boolean 例: 输出结果为: true false 说明:它的cons

  • 我正在尝试将文件从mongoDB读取到本地。 我的代码如下:STRING=“myLocalPath”PATH=STRING.json 我得到错误-对象类型'ObjectId'是不是JSON序列化...请建议。

  • 我有一个api,我正在尝试使用Flask Pymongo存储/发布一个用户对象。 但是,我得到了以下错误 文件“/home/kay/.local/share/virtualenvs/server-iT4jZt3h/lib/python3.7/site-packages/flask/json/i│ 尼特。py”,第321行,在jsonify中 │ 转储(数据,缩进=缩进,分隔符=分隔符)“\n”,│