JSON to Javascript Class
Asked Answered
H

2

34

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
}
Hearthside answered 13/9, 2018 at 13:47 Comment(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.Desiderative
Possible duplicate of convert javascript plain object into model class instanceGrapple
By the way, js has real getters do you could do get fullname() { return this.firstname + " " + this.lastname; } and then console.log(student.fullname)Crape
@Hearthside 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.Hearthside
C
72

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.

Crape answered 13/9, 2018 at 13:54 Comment(1)
this answer is correct but still it doesn't help me with code completion :(Rearm
E
6

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.

Erlanger answered 24/6, 2021 at 8:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.