我如何 serialize/deserialize Typescript 中的复杂对象,例如反序列化的对象与序列化的对象具有相同的类型
How could I serialize/deserialize complex objects in Typescript such as the deserialized object is of the same type as the object that was serialized
我有一个复杂的对象,我想序列化和反序列化并获得一个相同类型的对象。
let workflow = new Workflow();
console.log(`workflow is instanceof Workflow: ${workflow instanceof Workflow}`);
console.log(workflow);
let json = JSON.stringify(workflow);
console.log(json);
let workflow2 = JSON.parse(json) as Workflow;
console.log(workflow2);
console.log(`workflow2 is instanceof Workflow: ${workflow2 instanceof Workflow}`);
let workflow3: Workflow = JSON.parse(json) as Workflow;
console.log(workflow3);
console.log(`workflow3 is instanceof Workflow: ${workflow3 instanceof Workflow}`);
控制台输出为:
是否有开箱即用的解决方案,或者我需要手动重新实例化复杂对象并设置其所有属性?
您可以将对象的 fromJSON()
与 reviver
函数一起使用,以 JSON.parse()
实现您想要的效果。
例如:
type Serialized<T> = Pick<T, keyof T> & { _type: string };
class Workflow {
foo: number;
constructor(foo: number) {
this.foo = foo;
}
public toJSON(): Serialized<Workflow> {
return {
_type: this.constructor.name,
...this
};
}
public static fromJSON(source: Serialized<Workflow>): Workflow {
return new Workflow(source.foo);
}
}
function reviver(key: string, value: any): any {
if (typeof value === "object" && value && "_type" in value) {
switch (value._type) {
case "Workflow": return Workflow.fromJSON(value);
}
}
return value;
}
const w = new Workflow(42);
console.log(w instanceof Workflow);
const s = JSON.stringify(w);
console.log(s);
const w2 = JSON.parse(s, reviver) as Workflow;
console.log(w2.foo);
console.log(w2 instanceof Workflow);
打印:
true
{"_type":"Workflow","foo":42}
42
true
在 playground 亲自尝试!
Is there an out of the box solution for this...
我制作了一个名为 esserializer 的 npm 模块来解决这个问题:在序列化期间以普通 JSON 格式保存 JavaScript/TypeScript class 实例,连同它的class姓名信息:
const ESSerializer = require('esserializer');
class Workflow {
foo:number;
constructor(foo:number) {
this.foo = foo;
}
}
const w = new Workflow(42);
console.log(w instanceof Workflow);
const s = ESSerializer.serialize(w);
console.log(s);
稍后,在反序列化阶段(可能在另一台机器上),esserializer 可以递归反序列化对象实例,保留所有 Class/Property/Method 信息,使用相同的 class 定义:
const o = ESSerializer.deserialize(s, [Workflow]);
console.log(o.foo); // 42
console.log(o instanceof Workflow); // true
我有一个复杂的对象,我想序列化和反序列化并获得一个相同类型的对象。
let workflow = new Workflow();
console.log(`workflow is instanceof Workflow: ${workflow instanceof Workflow}`);
console.log(workflow);
let json = JSON.stringify(workflow);
console.log(json);
let workflow2 = JSON.parse(json) as Workflow;
console.log(workflow2);
console.log(`workflow2 is instanceof Workflow: ${workflow2 instanceof Workflow}`);
let workflow3: Workflow = JSON.parse(json) as Workflow;
console.log(workflow3);
console.log(`workflow3 is instanceof Workflow: ${workflow3 instanceof Workflow}`);
控制台输出为:
是否有开箱即用的解决方案,或者我需要手动重新实例化复杂对象并设置其所有属性?
您可以将对象的 fromJSON()
与 reviver
函数一起使用,以 JSON.parse()
实现您想要的效果。
例如:
type Serialized<T> = Pick<T, keyof T> & { _type: string };
class Workflow {
foo: number;
constructor(foo: number) {
this.foo = foo;
}
public toJSON(): Serialized<Workflow> {
return {
_type: this.constructor.name,
...this
};
}
public static fromJSON(source: Serialized<Workflow>): Workflow {
return new Workflow(source.foo);
}
}
function reviver(key: string, value: any): any {
if (typeof value === "object" && value && "_type" in value) {
switch (value._type) {
case "Workflow": return Workflow.fromJSON(value);
}
}
return value;
}
const w = new Workflow(42);
console.log(w instanceof Workflow);
const s = JSON.stringify(w);
console.log(s);
const w2 = JSON.parse(s, reviver) as Workflow;
console.log(w2.foo);
console.log(w2 instanceof Workflow);
打印:
true
{"_type":"Workflow","foo":42}
42
true
在 playground 亲自尝试!
Is there an out of the box solution for this...
我制作了一个名为 esserializer 的 npm 模块来解决这个问题:在序列化期间以普通 JSON 格式保存 JavaScript/TypeScript class 实例,连同它的class姓名信息:
const ESSerializer = require('esserializer');
class Workflow {
foo:number;
constructor(foo:number) {
this.foo = foo;
}
}
const w = new Workflow(42);
console.log(w instanceof Workflow);
const s = ESSerializer.serialize(w);
console.log(s);
稍后,在反序列化阶段(可能在另一台机器上),esserializer 可以递归反序列化对象实例,保留所有 Class/Property/Method 信息,使用相同的 class 定义:
const o = ESSerializer.deserialize(s, [Workflow]);
console.log(o.foo); // 42
console.log(o instanceof Workflow); // true