Angular 5 / Typescript - 如何将复杂的 json 对象转换为类

Posted

技术标签:

【中文标题】Angular 5 / Typescript - 如何将复杂的 json 对象转换为类【英文标题】:Angular 5 / Typescript - How to cast complex json object to a class 【发布时间】:2018-05-17 21:47:06 【问题描述】:

我正在尝试将一个复杂的(多个类型类)json 响应对象(我从我的 nodejs/mongoose 后端接收)转换为一个打字稿类。

moment 类包含用户类型的作者和评论类型的 cmets 数组。

moment.model.ts

    import  Comment  from './comment.model';
import  User  from './user.model';

export class Moment 

    _id?: string = null;
    body?: string = null;
    _author?: User = null;
    likes?: any[] = [];
    dislikes?: any[] = [];
    _comments?: Comment[] = [];
    created_at?: string = null;
    updated_at?: string = null;


    constructor(data?: Moment) 
        console.log(data);
        if (data) 
            this.deserialize(data);
        
    

    private deserialize(data: Moment) 
        const keys = Object.keys(this);

        for (const key of keys) 
            if (data.hasOwnProperty(key)) 
                this[key] = data[key];
            
        
    

    public get author(): User 
        return this._author;
    
    public set author(data: User) 
        this._author = new User(data);
    

    public get comments(): Comment[] 
        return this._comments;
    
    public set comments(data: Comment[]) 
        this._comments = data.map(c => new Comment(c));
    

comment.model.ts

    export class Comment 

    _id?: string = null;
    body?: string = null;
    moment?: any = null;
    author?: any = null;
    likes?: any[] = [];
    dislikes?: any[] = [];
    parent?: any = null;
    replies?: any = null;
    updated_at?: string = null;
    created_at?: string = null;

    constructor(data?: Comment) 
        console.log(data);
        if (data) 
            this.deserialize(data);
        
    

    private deserialize(data: Comment) 
        const keys = Object.keys(this);

        for (const key of keys) 
            if (data.hasOwnProperty(key)) 
                this[key] = data[key];
            
        
    


user.model.ts

 export class User 

    _id?: string = null
    updated_at?: string = null;
    created_at?: string = null;
    profile?: any = null;
    phone?: any = null;
    email?: any = null;
    followers: any[] = [];
    following: any[] = [];
    isOnline: any = null;
    socketId: any = null;


    constructor(data?: User) 
        console.log(data);
        if (data) 
            this.deserialize(data);
        
    

    private deserialize(data: User) 
        const keys = Object.keys(this);

        for (const key of keys) 
            if (data.hasOwnProperty(key)) 
                this[key] = data[key];
            
        
    

moment.service.ts

    get(moment_id) 

    let endpoint = this.path + moment_id;

    return this.apiService.get(endpoint)
        .map((res) => new Moment(res.data));


moment-detail.component.ts

this.route.params.switchMap((params) => 
    let moment_id = params['id'];
    return this.momentService.get(moment_id);
).subscribe((res) => 

    this.moment = res;
    console.log(this.moment);
);

当我调用我的服务时,我将 json 分配给一个新的 Moment 类。然后在组件中尝试打印 this.moment。一切都很好,除了作者和一个空/空的 cmets。

【问题讨论】:

_authorUser 类型,只有当你像new User( data[key]) 这样调用时,值才会分配给_author 的成员。否则,由于类型兼容性,您将收到错误并给出预期的 null。 如果你带一个 Moment 的例子,我们可以更容易地测试它。你不觉得吗?另外我认为你应该删除 javascript 标签,因为在这段代码中没有任何 javascript 代码(即使你使用 node.js 作为后端)。就像好奇一样,为什么要使用复制构造函数(在构造函数内部反序列化)?你真的需要它吗? @SantoshHegde ye 我想我理解这个问题,有解决方案吗? @JTejedor 是的,我需要它,这就是重点,我试图将 json 数据转换为 typescript 类。 这不是真正的铸造。您正在构建一个 Moment(与 new Moment),但我没有看到其他类在任何地方被调用? 【参考方案1】:

你可以试试

this[key]=( key=='_author' ? new User(data[key]):(key=='_comments'?new Comment(data[key]): data[key]))

或者

if(key=='_author')
    this[key]=new User(data[key]);
else if(key=='_comments')
    this[key]=new Comment(data[key]);
else
    this[key]=data[key]

【讨论】:

谢谢你,虽然这不是它帮助我的正确解决方案 最好重写你的代码。写的不好。【参考方案2】:

Moment 中的 deserialize 方法以相同的方式处理每个字段,只是从 JSON 中复制值。这意味着它永远不会构造 UserComment 对象。您可能应该“手动”编写它以正确处理每个属性,而不是使用循环。

【讨论】:

是的,我不需要 getter 和 setter,只需要重建我的班级。我只是想知道这是多么有效。 高效在什么意义上?很少值得担心这样的事情的运行时效率。更重要的是考虑可维护性。 对不起,这就是我的意思,我试图将一些与时刻相关的函数重构到模型中,而不是分散在组件中。

以上是关于Angular 5 / Typescript - 如何将复杂的 json 对象转换为类的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 5 中从 Typescript 调用 JavaScript 函数?

从 API 响应读取响应标头 - Angular 5 + TypeScript

typescript Angular 5安全html管道

从 Angular 2 Typescript 播放 HTML 5 视频

typescript 5#todoapp-angular-ngrx

typescript 5#todoapp-angular-ngrx