1

I know JSON.stringify doesn't stringify function, but what's the good practice because hydration is really exhausting. I don't want to create a new object. Any idea ?

class pers {
    name = "";
    last = "";

    constructor(name: string, last: string) {
        this.name = name;
        this.last = last;
    }

    alo() {
        alert(this.name);
    }
}

let pa = new pers("ben", "troq");
let s = JSON.stringify(pa);
let o = <pers>JSON.parse(s);
let pb = new pers("", "");

pb = o;
pb.alo();
2
  • stackoverflow.com/questions/8111446/… Commented May 1, 2016 at 15:53
  • 6
    Unrelated, but do yourself a favour and make the code consistent (put spaces around = everywhere, or do it nowhere if that makes you happier) and write out names (class person, with attributes firstname and lastname for example, instead of pers, name, last). What would pa, s, o and pb even stand for? Commented May 1, 2016 at 15:57

3 Answers 3

5

The problem is this line:

let o = <pers>JSON.parse(s);

I belive you think this is a type-cast, but it is not. This is a type-assertion, which does not imply runtime support. Basically, you are only telling the compiler to believe o is of type pers, but that is not true at runtime:

o instanceof pers; // false

You will either need to manually create the object instance using your JSON as Nitzan suggests, or create a routine that reads some metadata information to automatically create the correct instances with the corresponding properties.


For the latter approach, I would recommend trying out TypedJSON, which I created to provide an elegant and widely adaptable solution to this exact problem:

@JsonObject
class pers {
    @JsonMember name = "";
    @JsonMember last = "";

    constructor(name?: string, last?: string) {
        this.name = name;
        this.last = last;
    }

    alo() {
        alert(this.name);
    }
}
let o = TypedJSON.parse(s, pers);
o instanceof pers; // true
o.alo(); // "ben"

Note the parameterless constructor, that is required (in most similar systems, as well).

This solution builds on ReflectDecorators, but it's not required (however, without it you will need to manually specify the constructor function of properties: @JsonMember({ type: String }) ... for example).

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

Comments

1

How about separating the data from the functionality?

interface PersData {
    name: string;
    last: string;
}

class pers {
    private data: PersData;

    constructor(data: PersData | string) {
        this.data = typeof data === "string" ? JSON.parse(data) : data;
    }

    alo() {
        alert(this.data.name);
    }
}

Comments

1

replace:

let o  = <pers>JSON.parse(s);
let pb = new pers("", "");

pb = o;
pb.alo();

with:

let o  = JSON.parse(s);
let pb = Object.create(pers.prototype);
Object.assign(pb, o);

pb.alo();

It should work. Object.create (ES5.1) creates an object whose linked prototype is the one from the pers class but without running the pers constructor. Then Object.assign (ES6) copies the properties from the object unserialized from JSON to the object referenced by pb. Because the prototype was correctly set by Object.create calling the methods will work.

2 Comments

Can you explain your answer instead of just putting code in here? What is the key thing that makes your answer work? I ask because with an explanation others can learn from your answer and apply that to other questions. That is what stackoverflow is about --- not blindly copying & pasting some code.
Sorry, I thought the snippet was self-evident. Edited and added an explanation.

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.