35

I have a http request that gets this Json object from a nosql database:

let jsonBody = {
    birthday : 1997,
    firstname: 'foo',
    lastname:'bar'
}

Then I want to load this information into the Student model:

class Student{
    constructor(){

    }

    getFullname(){
        return this.lastname+' '+this.firstname
    }
    getApproxAge(){
        return 2018- this.birthday
    }
}

Normally, I would add this method to this class:

fromJson(json){
    this.studentId = json.studentId;
    this.birthday = json.birthday;
    this.firstname = json.firstname;
    this.lastname = json.lastname;
}

I would use it as follow:

let student = new Student()
student.fromJson(jsonBody)
console.log(student.getFullname())
console.log(student.getApproxAge())

This works fine but my problem is I have: 100 proprieties in reality. Will I have to write all proprities one by one in the fromJson method?

And also, if a propriety name has change, let's say: lastname became LastName, I will have to fix it?

Is there a simpler way to just assign these values to the object student dynamically but keep all of its methods??

Something like this:

fromJson(json){
    this = Object.assign(this, json) //THIS IS NOT WORKING
}
4
  • You could do something like your last snippet but it would probably be better if you manually do this.lastname = data.lastname and so on for each property. This will protect you if in the future the data you get does turn into LastName, since you only need to modify the initialisation code. Related, you probably want to initialise by data, so you can pass the server response in the constructor new Student(responseData) and do all the property setting there. Commented Sep 13, 2018 at 13:53
  • 2
    Possible duplicate of convert javascript plain object into model class instance Commented Sep 13, 2018 at 14:00
  • By the way, js has real getters do you could do get fullname() { return this.firstname + " " + this.lastname; } and then console.log(student.fullname) Commented Sep 13, 2018 at 14:14
  • @TSR You might want to use Typescript . it is a superset of javascript does allows you to check the types, in other it will alert you if one propriety is missing or incorrect. Commented Mar 14, 2019 at 19:06

3 Answers 3

75

Just assign to an instance:

 static from(json){
   return Object.assign(new Student(), json);
 }

So you can do:

 const student = Student.from({ name: "whatever" });

Or make it an instance method and leave away the assignemnt:

 applyData(json) {
   Object.assign(this, json);
 }

So you can:

 const student = new Student;
 student.applyData({ name: "whatever" });

It could also be part of the constructor:

 constructor(options = {}) {
  Object.assign(this, options);
 }

Then you could do:

 const student = new Student({ name: "whatever" });

And also, if a property name has changed, let's say: lastname became LastName, I will have to fix it?

Yes you will have to fix that.

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

2 Comments

this answer is correct but still it doesn't help me with code completion :(
note this is not a deep copy, if you have an object on a key "x", that object will be overwritten by the assign, so if that object is an instance of a class or a function, you'll need to create if manually after the assign()
7

There is no way in javascript to deserialize json into classes. So I wrote a library ts-serializable that solves this problem.

import { jsonProperty, Serializable } from "ts-serializable";

export class User extends Serializable {

    @jsonProperty(String)
    public firstName: string = ''; // default value necessarily

    @jsonProperty(String, void 0)
    public lastName?: string = void 0; // default value necessarily

    @jsonProperty(Date)
    public birthdate: Date = new Date(); // default value necessarily

    public getFullName(): string {
        return [
            this.firstName,
            this.lastName
        ].join(' ');
    }

    public getAge(): number {
        return new Date().getFullYear() - this.birthdate.getFullYear();
    }
}

const user: User = new User().fromJSON(json);
user.getFullName(); // work fine and return string
user.getAge(); // work fine and return number

// or
const user: User = User.fromJSON(json);
user.getFullName(); // work fine and return string
user.getAge(); // work fine and return number

The library also checks types during deserialization.

Comments

0

One can also use Object.create API to create instance of a class from JSON.

This is suitable for cases when constructor requires parameters that you don't have - since it's not called.
In your case it would look like this:

const student = Object.create(Student.prototype, Object.getOwnPropertyDescriptors(json));

See also:

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.