我不清楚序列化/反序列化应该如何作用于 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()”而不是“{}”吗?或者我只是应该在序列化中包含对象的原型(prototype)和构造函数属性?还有什么我想念的吗?我这样做是不是很愚蠢?我没有使用通用序列化/反序列化代码有两个原因:
编辑:请原谅我缺乏正确的术语; 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:从 Šime Vidas 的回答中获取代码,我添加了一个名为“设备”的相关对象:
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 );
现在的问题是如何最好地合并这些依赖对象,因为再一次,对象的“类型”(原型(prototype)?)被 JSON 丢失了。我们为什么不运行构造函数,而是简单地更改序列化和反序列化函数,以确保对象只需要像这样构造一次而不是创建和复制?
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/但是,您的情况更复杂,因此您需要定义一个自定义序列化函数。
关于类型化对象的 Javascript 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8657199/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳