简体   繁体   中英

Deserialize a JSON object into its original class

I am trying to serialize/deserialize an object. I am thinking that the best way would be to save the path to the file that called as part of the json, but I am unsure of how to get said path.

Can getting this path to the file ( A.ts / B.ts ) be done when called within the parent ( Base.ts )?

Is there maybe a better approach to doing this? I am trying to take a class created in the main node process, and and pass it to a worker process, the only why to do this that I can see is to serialize/deserialize the class somehow.

// src/Base.ts
export abstract class Base {

  public serialize() {
    return JSON.stringify({path: '', obj: this})
  }

  public static deserialize(json: string) {
    let { path, obj } = JSON.parse(json) as { path: string, obj: { [key: string]: any } }

    let newable = require(path)
    let o = new newable
    return Object.assign(o, obj)
  }

}

// src/filter/A.ts
export class A extends Base {
  public cat: string = 'meow'
  public sayHi() { return this.cat }
}

// src/filter/B.ts
export class B extends Base {
  public dog: string = 'woof'
  public sayHi() { return this.dog }
}

// test.ts
let serializedA = new A().serialize()
let serializedB = new B().serialize()
// Create child...
let worker = cp.fork(path.join(__dirname, './worker'), [], { silent: true })
worker.send({ serializedA, serializedB })

// worker.ts
process.on('message', msg => {
  let classA = Base.deserialize(msg.serializedA)
  let classB = Base.deserialize(msg.serializedB)
})

The simplest way that comes to mind would be to have a set of class names associated with callbacks that would require the appropriate classes.

// src/JsonIO.ts
export class JsonIO {

    private _classes: { name: string, callback: () => { new(): any } }[] = []

    public serialize(obj: any): string {
        return JSON.stringify({ class: obj.constructor.name, value: obj })
    }

    public deserialize(json: string) {
        const obj = JSON.parse(json) as { class: string, value: any }
        const clazz = this._classes.find(c => c.name == obj.class)
        if(!clazz) return obj.value
        return Object.assign(new (clazz.callback()), obj.value)
    }

    public registerClass(name: string, callback: () => { new(): any }) {
        this._classes.push({ name, callback })
    }

}

// src/Base.ts
export abstract class Base { /* ... */ }

// src/filter/A.ts
export class A {
    public cat: string = 'meow'
}

// src/filter/B.ts
export class B {
    public dog: string = 'woof'
}

// test.ts
const io = new JsonIO()
io.registerClass('A', () => A /* require('filter/A.ts') */)
io.registerClass('B', () => B /* require('filter/B.ts') */)

const serializedA = io.serialize(new A)
const serializedB = io.serialize(new B)

const a = io.deserialize(serializedA)
const b = io.deserialize(serializedB)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM