简体   繁体   中英

Best practice/only possibility. "Json to Javascript / Typescript Object by constructor"

I started developing with angular / typescript and created a service for my .NET Core API and I like to know what's the best way to get a clean and reliable object from my service.

I have an .NET CORE REST API returning a json result represented by the class definition below.

Service: demoservice.getDemo().subscribe((val) => new Demo(val));

Demo-Class is the following code:

export class Demo  {
    public id : number;
    public name : string;
    public subDemo: SubDemo;

    constructor(demo: Demo) {
      this.id = demo.id;
      this.name = demo.name;
      this.subDemo = new SubDemo(demo.subDemo);
    }
}

export class SubDemo {
    public demoList : ListDemo[]

    constructor(subDemo: SubDemo) {
        this.demoList = new Array<ListDemo>();
        subDemo.demoList.forEach(dl => {
            this.demoList.push(new ListDemo(dl))
        });
    }
}

export class ListDemo {
    constructor(listdemo : ListDemo) {
        this.birthday = listdemo.birthday;
        this.smoker = listdemo.smoker;    
    }

    get birthDayFormatted() : Date {
        return new Date(this.birthday);
    }

    public birthday : string;
    public smoker : boolean;
}

I this the best way (full implement all constructors) to create a object. Please note I like to use the "getter" - functionality of my ListDemo Class.

Is there no better way? I just found some Object.clone / Object.assign / Object.create.

But none of this solution is comprehensive...

I am really interested in your experience..

Since you're using better & best I will answer with my, probably unwanted, opinion. Disclaimer: I'm no guru, this answer is based on opinion, feel free to disregard.

Don't do it. Your server has a set of objects in its domain, probably some kind of problem solving or data storage domain.

Your client has a set of objects in its domain, typically focused on presenting the data to the user and allowing the user to understand and manipulate it.

Both of these domains may have objects that have the same name or are based on the same real world concept. It can be tempting to feel like they are the same domain with the same objects. They are not. If they were the same you would not be writing a client and a server you would be writing two of the same thing. The two should communicate with pure data objects. In TS this means you should only create an interface, not a class, for the objects you receive from the server.

Instead, start over. Create a new domain based on what you want to appear in the API. If you design your API from the top (UI) down to the bottom (access services) you'll likely find that you don't have a one-to-one mapping between objects. On the occasions you do then you can probably get away with the occasional assign / merge (see below) but I've personally never found reason to do more than what you posted above.

Should you persist you may come across the option to reassign the prototype of the JSON literal from the base object to the class the data represents but that is a contentious topic and potential performance pitfall. . Your best bet is probably to just do a recursive/deep assign like Lodash's merge .

Just use interfaces not classes.

export interface Demo  {
  id: number;
  name: string;
  subDemo: SubDemo;
}

export interface SubDemo {
  demoList: ListDemo[];
}

export interface ListDemo {
    birthday: string;
    smoker: boolean;
}

and your api should return the same shape, you should just be able to go

getDemo(): Observable<Demo> {
  return this.http.get<Demo>('url');
}

in your service and in your component assign it to a property

demo$ = this.service.getDemo();

and then use the observable with the async pipe in your template.

<ng-container *ngIf="demo$ | async as demo">
  {{ demo | json }}
</ng-container>

The less you have to manipulate your data the better. I have a VS pluging that allows you to paste C# classes into TS files and it converts them to TypeScript interfaces on the fly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM