Blake
Blake

Reputation: 83

JSON to Javascript Object with methods

I have a Typescript class that has methods on it. I end up transferring these objects from the server to the browser through REST where the JSON representation of course loses the methods and prototype information. I want to turn the JSON back into the object with the methods so I can use them on the client side. I've been using a static method that will take in the JSON object and recreate my object but it's a pretty manual process.

Is there a better way to do it?

class Rectangle {
    constructor(public width: number, public height: number) { }
    public getArea(): number {
        return this.width * this.height;
    }

    public static fromPojo(pojo: any): Rectangle {
        if (pojo
            && pojo.width !== undefined
            && pojo.height !== undefined) {
                return new Rectangle(pojo.width, pojo.height);
            }
        throw new Error("Pojo is not a Rectangle");
    }
}

let rect = new Rectangle(10, 20);
console.log(rect.getArea()); // 200
let json = JSON.stringify(rect); // {"width":10,"height":20}

let rectFromJson = <Rectangle>JSON.parse(json);
console.log(rectFromJson.getArea()); // Error: rectFromJson.getArea is not a function

let rectFromPojo = Rectangle.fromPojo(JSON.parse(json));
console.log(rectFromPojo.getArea()); // 200

If a property gets added to the object, I have to make sure I update the fromPojo() method, making this tactic error-prone. Ideally I want to get rid of the static fromPojo(pojo) method in favor of something more dependable/automatic.

Update: Here's the code working with Serializr, as suggested by Nick Uraltsev. Much less error prone but loses the constructor params. I would prefer to be able to keep the constructor params.

import { deserialize, serializable, serialize } from "serializr";
class Rectangle {
    @serializable
    public width: number;
    @serializable
    public height: number;

    public getArea(): number {
        return this.width * this.height;
    }
}

let rect = new Rectangle();
rect.width = 10;
rect.height = 20;

let serJson = serialize(rect);
console.log(serJson); // { width: 10, height: 20 }

let reconstructedRect = deserialize(Rectangle, serJson);
console.log(reconstructedRect.getArea()); // 200

Upvotes: 0

Views: 157

Answers (1)

Nick Uraltsev
Nick Uraltsev

Reputation: 25897

Take a look at Serializr. Looks like it does exactly what you need.

Upvotes: 1

Related Questions