Normalized on tk-base
This commit is contained in:
parent
49e2c36673
commit
f1c07354c2
14 changed files with 6973 additions and 2527 deletions
10
.editorconfig
Normal file
10
.editorconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
max_line_length = off
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,5 +1,5 @@
|
|||
.venv
|
||||
dist
|
||||
node_modules
|
||||
coverage
|
||||
|
||||
.rts2_cache_*
|
||||
.coverage
|
||||
/dist/
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "node"
|
||||
after_success:
|
||||
- "npm run codecov"
|
37
README.md
37
README.md
|
@ -1,11 +1,6 @@
|
|||
tk-serializer
|
||||
=============
|
||||
|
||||
[![Build status](https://img.shields.io/travis/thunderk/tk-serializer.svg)](https://travis-ci.org/thunderk/tk-serializer)
|
||||
[![Code coverage](https://img.shields.io/codecov/c/github/thunderk/tk-serializer.svg)](https://codecov.io/gh/thunderk/tk-serializer)
|
||||
[![NPM version](https://img.shields.io/npm/v/tk-serializer.svg)](https://www.npmjs.com/package/tk-serializer)
|
||||
[![Minified size](https://img.shields.io/bundlephobia/min/tk-serializer.svg)](https://bundlephobia.com/result?p=tk-serializer)
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
|
@ -15,19 +10,39 @@ Deep objects state may be serialized to a string, and reconstructed back.
|
|||
|
||||
Class instances are reconstructed properly, as long as they are in the provided namespace. Circular references are handled.
|
||||
|
||||
Be warned that resulting serialized value may be quite large.
|
||||
|
||||
Typescript definitions are included.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
npm install tk-serializer
|
||||
Import in node:
|
||||
|
||||
```shell
|
||||
npm install tk-serializer
|
||||
```
|
||||
|
||||
```javascript
|
||||
import { Serializer } from "tk-serializer";
|
||||
```
|
||||
|
||||
Import in browser:
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/tk-serializer"></script>
|
||||
```
|
||||
|
||||
```javascript
|
||||
const Serializer = tkSerializer.Serializer;
|
||||
```
|
||||
|
||||
Use
|
||||
---
|
||||
|
||||
Suppose you have 2 classes Class1 and Class2, whose instances you want to serialize.
|
||||
|
||||
```typescript
|
||||
import { Serializer } from "tk-serializer";
|
||||
Suppose you have 2 classes Class1 and Class2, whose instances you want to serialize:
|
||||
|
||||
```javascript
|
||||
const namespace = {
|
||||
Class1,
|
||||
Class2
|
||||
|
@ -44,7 +59,7 @@ let serializer = new Serializer(namespace);
|
|||
serializer.addIgnoredClass("Class3");
|
||||
|
||||
// Serialize the object to a string
|
||||
let state: string = serializer.serialize(obj);
|
||||
let state = serializer.serialize(obj);
|
||||
|
||||
// Reconstruct the object back (*c* will be undefined)
|
||||
let nobj = serializer.unserialize(state);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# source activate_node
|
||||
|
||||
vdir="./.venv"
|
||||
expected="10.15.0"
|
||||
expected="10.16.3"
|
||||
|
||||
if [ \! -f "./activate_node" ]
|
||||
then
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
module.exports = {
|
||||
transform: {
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
},
|
||||
testRegex: "src/test\\.ts$",
|
||||
testURL: "http://localhost:8014",
|
||||
moduleFileExtensions: [
|
||||
"ts",
|
||||
"js",
|
||||
"json",
|
||||
"node"
|
||||
],
|
||||
restoreMocks: true,
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: [
|
||||
"src/main.ts",
|
||||
],
|
||||
coverageDirectory: "out/coverage",
|
||||
coverageReporters: [
|
||||
"lcovonly",
|
||||
"html",
|
||||
"text-summary"
|
||||
]
|
||||
transform: {
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
},
|
||||
moduleFileExtensions: [
|
||||
"ts",
|
||||
"js",
|
||||
"json",
|
||||
"node"
|
||||
],
|
||||
restoreMocks: true,
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: [
|
||||
"src/**/*.ts",
|
||||
"!src/**/*.test.ts",
|
||||
],
|
||||
coverageDirectory: ".coverage",
|
||||
coverageReporters: [
|
||||
"lcovonly",
|
||||
"html",
|
||||
"text-summary"
|
||||
]
|
||||
}
|
||||
|
|
8777
package-lock.json
generated
8777
package-lock.json
generated
File diff suppressed because it is too large
Load diff
43
package.json
43
package.json
|
@ -1,35 +1,32 @@
|
|||
{
|
||||
"name": "tk-serializer",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "Serializer of javascript objects",
|
||||
"main": "dist/main.js",
|
||||
"types": "dist/main.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest",
|
||||
"prepare": "npm run build",
|
||||
"prepublishOnly": "npm test",
|
||||
"codecov": "codecov"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"author": {
|
||||
"name": "Michael Lemaire",
|
||||
"email": "michael@thunderk.net",
|
||||
"name": "Michaël Lemaire",
|
||||
"url": "https://thunderk.net"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thunderk/tk-serializer.git"
|
||||
"url": "https://code.thunderk.net/tslib/tk-serializer.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"license": "ISC",
|
||||
"source": "src/index.ts",
|
||||
"main": "dist/tk-serializer.js",
|
||||
"umd:main": "dist/tk-serializer.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "npx tk-base build",
|
||||
"test": "npx tk-base test",
|
||||
"prepare": "npm run build",
|
||||
"prepublishOnly": "npm test",
|
||||
"normalize": "npx tk-base normalize"
|
||||
},
|
||||
"files": [
|
||||
"/src",
|
||||
"/dist"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/jest": "^23.3.10",
|
||||
"codecov": "^3.1.0",
|
||||
"jest": "^23.6.0",
|
||||
"ts-jest": "^23.10.5",
|
||||
"ts-node": "^7.0.1",
|
||||
"typescript": "^3.2.2"
|
||||
"tk-base": "^0.1.2"
|
||||
}
|
||||
}
|
||||
|
|
1
src/index.ts
Normal file
1
src/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { Serializer } from "./serializer";
|
165
src/main.ts
165
src/main.ts
|
@ -1,165 +0,0 @@
|
|||
const merge = Object.assign;
|
||||
|
||||
const STOP_CRAWLING = {};
|
||||
|
||||
/**
|
||||
* Check if the argument is an instance of a class
|
||||
*/
|
||||
function isObject(value: any): boolean {
|
||||
return value instanceof Object && !Array.isArray(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively crawl through an object, yielding any defined value found along the way
|
||||
*
|
||||
* If *replace* is set to true, the current object is replaced (in array or object attribute) by the result of the callback
|
||||
*
|
||||
* *memo* is used to prevent circular references to be traversed
|
||||
*/
|
||||
function crawl(obj: any, callback: (item: any) => any, replace = false, memo: any[] = []) {
|
||||
if (isObject(obj)) {
|
||||
if (memo.indexOf(obj) >= 0) {
|
||||
return obj;
|
||||
} else {
|
||||
memo.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (obj !== undefined && obj !== null && typeof obj != "function") {
|
||||
let result = callback(obj);
|
||||
|
||||
if (result === STOP_CRAWLING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
let subresult = obj.map(value => crawl(value, callback, replace, memo));
|
||||
if (replace) {
|
||||
subresult.forEach((value, index) => {
|
||||
obj[index] = value;
|
||||
});
|
||||
}
|
||||
} else if (obj instanceof Object) {
|
||||
let subresult: any = {};
|
||||
for (let key in obj) {
|
||||
subresult[key] = crawl(obj[key], callback, replace, memo);
|
||||
}
|
||||
if (replace) {
|
||||
merge(obj, subresult);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of an object.
|
||||
*/
|
||||
function classname(obj: Object): string {
|
||||
return (<any>obj.constructor).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A deep serializer of javascript objects.
|
||||
*/
|
||||
export class Serializer {
|
||||
private namespace: any;
|
||||
private ignored: string[] = [];
|
||||
|
||||
constructor(namespace: any) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a class to the ignore list
|
||||
*/
|
||||
addIgnoredClass(name: string) {
|
||||
this.ignored.push(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an object from a constructor name
|
||||
*/
|
||||
private constructObject(ctype: string): Object {
|
||||
if (ctype == "Object") {
|
||||
return {};
|
||||
} else {
|
||||
let cl = this.namespace[ctype];
|
||||
if (cl) {
|
||||
return Object.create(cl.prototype);
|
||||
} else {
|
||||
console.error("Can't find class", ctype);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an object to a string
|
||||
*/
|
||||
serialize(obj: any): string {
|
||||
// Collect objects
|
||||
var objects: Object[] = [];
|
||||
var stats: any = {};
|
||||
crawl(obj, value => {
|
||||
if (isObject(value)) {
|
||||
var vtype = classname(value);
|
||||
if (vtype != "" && this.ignored.indexOf(vtype) < 0) {
|
||||
stats[vtype] = (stats[vtype] || 0) + 1;
|
||||
if (objects.indexOf(value) < 0) {
|
||||
objects.push(value);
|
||||
}
|
||||
return value;
|
||||
} else {
|
||||
return STOP_CRAWLING;
|
||||
}
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
//console.log("Serialize stats", stats);
|
||||
|
||||
// Serialize objects list, transforming deeper objects to links
|
||||
var fobjects = objects.map(value => <Object>{ $c: classname(value), $f: merge({}, value) });
|
||||
return JSON.stringify(fobjects, (key, value) => {
|
||||
if (key != "$f" && isObject(value) && !value.hasOwnProperty("$c") && !value.hasOwnProperty("$i")) {
|
||||
return { $i: objects.indexOf(value) };
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize a string to an object
|
||||
*/
|
||||
unserialize(data: string): any {
|
||||
// Unserialize objects list
|
||||
var fobjects = JSON.parse(data);
|
||||
|
||||
// Reconstruct objects
|
||||
var objects = fobjects.map((objdata: any) => merge(this.constructObject(objdata['$c']), objdata['$f']));
|
||||
|
||||
// Reconnect links
|
||||
crawl(objects, value => {
|
||||
if (value instanceof Object && value.hasOwnProperty('$i')) {
|
||||
return objects[value['$i']];
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Post unserialize hooks
|
||||
crawl(objects[0], value => {
|
||||
if (value instanceof Object && typeof value.postUnserialize === "function") {
|
||||
value.postUnserialize();
|
||||
}
|
||||
});
|
||||
|
||||
// First object was the root
|
||||
return objects[0];
|
||||
}
|
||||
}
|
105
src/serializer.test.ts
Normal file
105
src/serializer.test.ts
Normal file
|
@ -0,0 +1,105 @@
|
|||
import { Serializer } from "./serializer";
|
||||
|
||||
class TestSerializerObj1 {
|
||||
a: number;
|
||||
constructor(a = 0) {
|
||||
this.a = a;
|
||||
}
|
||||
}
|
||||
|
||||
class TestSerializerObj2 {
|
||||
a = () => 1
|
||||
b = [(obj: any) => 2]
|
||||
}
|
||||
|
||||
class TestSerializerObj3 {
|
||||
a = [1, 2];
|
||||
postUnserialize() {
|
||||
this.a.push(3);
|
||||
}
|
||||
}
|
||||
|
||||
const TEST_NS = {
|
||||
TestSerializerObj1,
|
||||
TestSerializerObj2,
|
||||
TestSerializerObj3
|
||||
};
|
||||
|
||||
describe("Serializer", () => {
|
||||
function checkReversability(obj: any, namespace = TEST_NS): any {
|
||||
var serializer = new Serializer(namespace);
|
||||
var data = serializer.serialize(obj);
|
||||
serializer = new Serializer(namespace);
|
||||
var loaded = serializer.unserialize(data);
|
||||
expect(loaded).toEqual(obj);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
it("serializes simple objects", () => {
|
||||
var obj = {
|
||||
"a": 5,
|
||||
"b": null,
|
||||
"c": [{ "a": 2 }, "test"]
|
||||
};
|
||||
checkReversability(obj);
|
||||
});
|
||||
|
||||
it("restores objects constructed from class", () => {
|
||||
var loaded = checkReversability(new TestSerializerObj1(5));
|
||||
expect(loaded.a).toBe(5);
|
||||
expect(loaded).toBeInstanceOf(TestSerializerObj1);
|
||||
});
|
||||
|
||||
it("stores one version of the same object", () => {
|
||||
var a = new TestSerializerObj1(8);
|
||||
var b = new TestSerializerObj1(8);
|
||||
var c = {
|
||||
'r': a,
|
||||
's': ["test", a],
|
||||
't': a,
|
||||
'u': b
|
||||
};
|
||||
var loaded = checkReversability(c);
|
||||
expect(loaded.t).toBe(loaded.r);
|
||||
expect(loaded.s[1]).toBe(loaded.r);
|
||||
expect(loaded.u).not.toBe(loaded.r);
|
||||
});
|
||||
|
||||
it("handles circular references", () => {
|
||||
var a: any = { b: {} };
|
||||
a.b.c = a;
|
||||
|
||||
checkReversability(a);
|
||||
});
|
||||
|
||||
it("ignores some classes", () => {
|
||||
var serializer = new Serializer(TEST_NS);
|
||||
serializer.addIgnoredClass("TestSerializerObj1");
|
||||
|
||||
var data = serializer.serialize({ a: 5, b: new TestSerializerObj1() });
|
||||
var loaded = serializer.unserialize(data);
|
||||
|
||||
expect(loaded).toEqual({ a: 5, b: undefined });
|
||||
});
|
||||
|
||||
it("ignores functions", () => {
|
||||
let serializer = new Serializer(TEST_NS);
|
||||
let data = serializer.serialize({ obj: new TestSerializerObj2() });
|
||||
let loaded = serializer.unserialize(data);
|
||||
|
||||
let expected = <any>new TestSerializerObj2();
|
||||
expected.a = undefined;
|
||||
expected.b[0] = undefined;
|
||||
expect(loaded).toEqual({ obj: expected });
|
||||
});
|
||||
|
||||
it("calls specific postUnserialize", () => {
|
||||
let serializer = new Serializer(TEST_NS);
|
||||
let data = serializer.serialize({ obj: new TestSerializerObj3() });
|
||||
let loaded = serializer.unserialize(data);
|
||||
|
||||
let expected = new TestSerializerObj3();
|
||||
expected.a = [1, 2, 3];
|
||||
expect(loaded).toEqual({ obj: expected });
|
||||
});
|
||||
});
|
165
src/serializer.ts
Normal file
165
src/serializer.ts
Normal file
|
@ -0,0 +1,165 @@
|
|||
const merge = Object.assign;
|
||||
|
||||
const STOP_CRAWLING = {};
|
||||
|
||||
/**
|
||||
* Check if the argument is an instance of a class
|
||||
*/
|
||||
function isObject(value: any): boolean {
|
||||
return value instanceof Object && !Array.isArray(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively crawl through an object, yielding any defined value found along the way
|
||||
*
|
||||
* If *replace* is set to true, the current object is replaced (in array or object attribute) by the result of the callback
|
||||
*
|
||||
* *memo* is used to prevent circular references to be traversed
|
||||
*/
|
||||
function crawl(obj: any, callback: (item: any) => any, replace = false, memo: any[] = []) {
|
||||
if (isObject(obj)) {
|
||||
if (memo.indexOf(obj) >= 0) {
|
||||
return obj;
|
||||
} else {
|
||||
memo.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (obj !== undefined && obj !== null && typeof obj != "function") {
|
||||
let result = callback(obj);
|
||||
|
||||
if (result === STOP_CRAWLING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
let subresult = obj.map(value => crawl(value, callback, replace, memo));
|
||||
if (replace) {
|
||||
subresult.forEach((value, index) => {
|
||||
obj[index] = value;
|
||||
});
|
||||
}
|
||||
} else if (obj instanceof Object) {
|
||||
let subresult: any = {};
|
||||
for (let key in obj) {
|
||||
subresult[key] = crawl(obj[key], callback, replace, memo);
|
||||
}
|
||||
if (replace) {
|
||||
merge(obj, subresult);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of an object.
|
||||
*/
|
||||
function classname(obj: Object): string {
|
||||
return (<any>obj.constructor).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A deep serializer of javascript objects.
|
||||
*/
|
||||
export class Serializer {
|
||||
private namespace: any;
|
||||
private ignored: string[] = [];
|
||||
|
||||
constructor(namespace: any) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a class to the ignore list
|
||||
*/
|
||||
addIgnoredClass(name: string) {
|
||||
this.ignored.push(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an object from a constructor name
|
||||
*/
|
||||
private constructObject(ctype: string): Object {
|
||||
if (ctype == "Object") {
|
||||
return {};
|
||||
} else {
|
||||
let cl = this.namespace[ctype];
|
||||
if (cl) {
|
||||
return Object.create(cl.prototype);
|
||||
} else {
|
||||
console.error("Can't find class", ctype);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize an object to a string
|
||||
*/
|
||||
serialize(obj: any): string {
|
||||
// Collect objects
|
||||
var objects: Object[] = [];
|
||||
var stats: any = {};
|
||||
crawl(obj, value => {
|
||||
if (isObject(value)) {
|
||||
var vtype = classname(value);
|
||||
if (vtype != "" && this.ignored.indexOf(vtype) < 0) {
|
||||
stats[vtype] = (stats[vtype] || 0) + 1;
|
||||
if (objects.indexOf(value) < 0) {
|
||||
objects.push(value);
|
||||
}
|
||||
return value;
|
||||
} else {
|
||||
return STOP_CRAWLING;
|
||||
}
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
//console.log("Serialize stats", stats);
|
||||
|
||||
// Serialize objects list, transforming deeper objects to links
|
||||
var fobjects = objects.map(value => <Object>{ $c: classname(value), $f: merge({}, value) });
|
||||
return JSON.stringify(fobjects, (key, value) => {
|
||||
if (key != "$f" && isObject(value) && !value.hasOwnProperty("$c") && !value.hasOwnProperty("$i")) {
|
||||
return { $i: objects.indexOf(value) };
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize a string to an object
|
||||
*/
|
||||
unserialize(data: string): any {
|
||||
// Unserialize objects list
|
||||
var fobjects = JSON.parse(data);
|
||||
|
||||
// Reconstruct objects
|
||||
var objects = fobjects.map((objdata: any) => merge(this.constructObject(objdata['$c']), objdata['$f']));
|
||||
|
||||
// Reconnect links
|
||||
crawl(objects, value => {
|
||||
if (value instanceof Object && value.hasOwnProperty('$i')) {
|
||||
return objects[value['$i']];
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Post unserialize hooks
|
||||
crawl(objects[0], value => {
|
||||
if (value instanceof Object && typeof value.postUnserialize === "function") {
|
||||
value.postUnserialize();
|
||||
}
|
||||
});
|
||||
|
||||
// First object was the root
|
||||
return objects[0];
|
||||
}
|
||||
}
|
105
src/test.ts
105
src/test.ts
|
@ -1,105 +0,0 @@
|
|||
import {Serializer} from "./main";
|
||||
|
||||
class TestSerializerObj1 {
|
||||
a: number;
|
||||
constructor(a = 0) {
|
||||
this.a = a;
|
||||
}
|
||||
}
|
||||
|
||||
class TestSerializerObj2 {
|
||||
a = () => 1
|
||||
b = [(obj: any) => 2]
|
||||
}
|
||||
|
||||
class TestSerializerObj3 {
|
||||
a = [1, 2];
|
||||
postUnserialize() {
|
||||
this.a.push(3);
|
||||
}
|
||||
}
|
||||
|
||||
const TEST_NS = {
|
||||
TestSerializerObj1,
|
||||
TestSerializerObj2,
|
||||
TestSerializerObj3
|
||||
};
|
||||
|
||||
describe("Serializer", () => {
|
||||
function checkReversability(obj: any, namespace = TEST_NS): any {
|
||||
var serializer = new Serializer(namespace);
|
||||
var data = serializer.serialize(obj);
|
||||
serializer = new Serializer(namespace);
|
||||
var loaded = serializer.unserialize(data);
|
||||
expect(loaded).toEqual(obj);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
it("serializes simple objects", () => {
|
||||
var obj = {
|
||||
"a": 5,
|
||||
"b": null,
|
||||
"c": [{ "a": 2 }, "test"]
|
||||
};
|
||||
checkReversability(obj);
|
||||
});
|
||||
|
||||
it("restores objects constructed from class", () => {
|
||||
var loaded = checkReversability(new TestSerializerObj1(5));
|
||||
expect(loaded.a).toBe(5);
|
||||
expect(loaded).toBeInstanceOf(TestSerializerObj1);
|
||||
});
|
||||
|
||||
it("stores one version of the same object", () => {
|
||||
var a = new TestSerializerObj1(8);
|
||||
var b = new TestSerializerObj1(8);
|
||||
var c = {
|
||||
'r': a,
|
||||
's': ["test", a],
|
||||
't': a,
|
||||
'u': b
|
||||
};
|
||||
var loaded = checkReversability(c);
|
||||
expect(loaded.t).toBe(loaded.r);
|
||||
expect(loaded.s[1]).toBe(loaded.r);
|
||||
expect(loaded.u).not.toBe(loaded.r);
|
||||
});
|
||||
|
||||
it("handles circular references", () => {
|
||||
var a: any = { b: {} };
|
||||
a.b.c = a;
|
||||
|
||||
checkReversability(a);
|
||||
});
|
||||
|
||||
it("ignores some classes", () => {
|
||||
var serializer = new Serializer(TEST_NS);
|
||||
serializer.addIgnoredClass("TestSerializerObj1");
|
||||
|
||||
var data = serializer.serialize({ a: 5, b: new TestSerializerObj1() });
|
||||
var loaded = serializer.unserialize(data);
|
||||
|
||||
expect(loaded).toEqual({ a: 5, b: undefined });
|
||||
});
|
||||
|
||||
it("ignores functions", () => {
|
||||
let serializer = new Serializer(TEST_NS);
|
||||
let data = serializer.serialize({ obj: new TestSerializerObj2() });
|
||||
let loaded = serializer.unserialize(data);
|
||||
|
||||
let expected = <any>new TestSerializerObj2();
|
||||
expected.a = undefined;
|
||||
expected.b[0] = undefined;
|
||||
expect(loaded).toEqual({ obj: expected });
|
||||
});
|
||||
|
||||
it("calls specific postUnserialize", () => {
|
||||
let serializer = new Serializer(TEST_NS);
|
||||
let data = serializer.serialize({ obj: new TestSerializerObj3() });
|
||||
let loaded = serializer.unserialize(data);
|
||||
|
||||
let expected = new TestSerializerObj3();
|
||||
expected.a = [1, 2, 3];
|
||||
expect(loaded).toEqual({ obj: expected });
|
||||
});
|
||||
});
|
|
@ -1,27 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"declaration": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": [
|
||||
"src/main.ts"
|
||||
"compilerOptions": {
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"preserveConstEnums": true,
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"es6"
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"coverage",
|
||||
"node_modules"
|
||||
]
|
||||
"target": "es6"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue