0

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

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that does work with a few modifications to my code. Serializr does require that I remove the constructor params which is unfortunate but maybe unavoidable.
Turns out it wasn't too hard to add support for constructor params. I've made a PR to the Serializr author. I'll update if/when it gets accepted.
PR was pulled in and is now available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.