From fd9bdfffddb7fa93b77b3b431d963f39aba5cccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 2 Mar 2015 01:00:00 +0100 Subject: [PATCH] Added recursive serialization --- src/scripts/game/Serializer.ts | 49 +++++++++++++++++++---- src/scripts/game/specs/Serializer.spec.ts | 10 +++++ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/scripts/game/Serializer.ts b/src/scripts/game/Serializer.ts index ccc2465..83b7949 100644 --- a/src/scripts/game/Serializer.ts +++ b/src/scripts/game/Serializer.ts @@ -3,11 +3,12 @@ module SpaceTac.Game { // Serializer to cascade through Serializable objects export class Serializer { + // List all classes that implement "Serializable", with their full path in SpaceTac.Game namespace collectSerializableClasses(container: any = null, path: string = ""): {[index: string]: typeof Serializable} { if (container) { var result: {[index: string]: typeof Serializable} = {}; for (var obj_name in container) { - if (obj_name) { + if (container.hasOwnProperty(obj_name)) { var obj = container[obj_name]; var obj_path = path + "." + obj_name; if (typeof obj === "object") { @@ -23,10 +24,11 @@ module SpaceTac.Game { } } + // Get the full path in SpaceTac namespace, of a serializable object getClassPath(obj: Serializable): string { var classes = this.collectSerializableClasses(); for (var class_path in classes) { - if (class_path) { + if (classes.hasOwnProperty(class_path)) { var class_obj = classes[class_path]; if (class_obj.prototype === obj.constructor.prototype) { return class_path; @@ -36,19 +38,52 @@ module SpaceTac.Game { return null; } + // Serialize an object to a string serialize(obj: Serializable): string { - var data = { - path: this.getClassPath(obj), - fields: obj - }; + var data = this.toData(obj); return JSON.stringify(data); } + // Load an object from a serialized string unserialize(sdata: string): Serializable { var data = JSON.parse(sdata); + var result = this.fromData(data); + return result; + } + + private toData(obj: Serializable): any { + var fields = {}; + for (var field_name in obj) { + if (obj.hasOwnProperty(field_name)) { + var field_value = obj[field_name]; + if (field_value instanceof Serializable) { + fields[field_name] = this.toData(field_value); + } else { + fields[field_name] = field_value; + } + } + } + + var data = { + path: this.getClassPath(obj), + fields: fields + }; + return data; + } + + private fromData(data: any): Serializable { var class_info = this.collectSerializableClasses()[data.path]; var obj = Object.create(class_info.prototype); - obj = Tools.merge(obj, data.fields); + for (var field_name in data.fields) { + if (data.fields.hasOwnProperty(field_name)) { + var field_value = data.fields[field_name]; + if (typeof field_value === "object" && field_value.hasOwnProperty("path")) { + obj[field_name] = this.fromData(field_value); + } else { + obj[field_name] = field_value; + } + } + } return obj; } } diff --git a/src/scripts/game/specs/Serializer.spec.ts b/src/scripts/game/specs/Serializer.spec.ts index fb0d9a5..0b2e120 100644 --- a/src/scripts/game/specs/Serializer.spec.ts +++ b/src/scripts/game/specs/Serializer.spec.ts @@ -55,5 +55,15 @@ module SpaceTac.Game.Specs { expect(loaded).toEqual(obj); expect((loaded).prepend("this is ")).toEqual("this is a string"); }); + + it("serializes and deserializes nested typescript objects", () => { + var serializer = new Serializer(); + var obj = new SerializableTestObj1(8, new SerializableTestObj2("test")); + var dumped = serializer.serialize(obj); + var loaded = serializer.unserialize(dumped); + + expect(loaded).toEqual(obj); + expect((loaded).b.prepend("this is a ")).toEqual("this is a test"); + }); }); }