简体   繁体   English

HttpClient Angular 9 将嵌套的 json 转换为嵌套的 object

[英]HttpClient Angular 9 converting nested json to nested object

I'm trying to see if there's a more elegant way other than using map to accomplish the following:我试图看看除了使用 map 之外是否有更优雅的方式来完成以下操作:

I have a class with an array of another object.我有一个 class 和另一个 object 阵列。 So my Meeting object has many users:所以我的会议 object 有很多用户:

import { User } from './user';

export class Meeting {
  _id?: string;
  name: string;
  roomSid?: string;
  users: User[];
  contentList: any;
  startDate: Date;
  endDate: Date;
  createDate: Date;
}

export class User {
  _id: string;
  firstName: string;
  lastName: string;
  dealerName: string;
  location: string;
  role: 'attendee' | 'host' | 'participant';
  videoServiceId: string;
  profilePic?: string;
  __v?: string;

  get isHost(): boolean {
    return this.role === 'host';
  }

  get isAttendee(): boolean {
    return this.role === 'attendee';
  }

  get isParticipant(): boolean {
    return this.role === 'participant';
  }

  get isClient(): boolean {
    return this.isAttendee || this.isParticipant;
  }
}

When I do:当我做:

this.httpClient
      .get<Meeting>(`${this.apiUrl}${meetingId}`)
      .pipe(
        catchError(this.handleError));

without using map to convert the received result from the get, the User object array is getting set incorrectly.如果不使用 map 转换从 get 接收到的结果,则用户 object 数组设置不正确。 My getters are undefined unless I do a Object.assign(new User, user).除非我执行 Object.assign(new User, user),否则我的吸气剂是未定义的。 HttpGet returns the Meeting as a Meeting class just fine, just not the objects inside. HttpGet 将会议返回为会议 class 就好了,只是不是里面的对象。

Is there something I'm missing or is this working as intended and I have no choice but to use map().有什么我遗漏的东西,还是按预期工作,我别无选择,只能使用 map()。 Although I feel that if I have another Object inside my User class, then things could get a bit messier.虽然我觉得如果我的用户 class 中有另一个 Object,那么事情可能会变得有点混乱。

For reference here is a response from the server:供参考,这里是来自服务器的响应:

{
    "users": [
        {
            "_id": "971c4160-c60c-11ea-8505-dff43e61059c",
            "firstName": "alex",
            "lastName": "oroszi",
            "dealerName": "here",
            "location": "here",
            "role": "attendee",
            "videoServiceId": "PA634a9331a9cad648bb6e6dbcea8e49a0"
        }
    ],
    "contentList": [],
    "_id": "5f0a005b627fb647f519118b",
    "name": "Room1",
    "startDate": "2020-07-11T16:00:00.000Z",
    "endDate": "2020-07-11T17:00:00.000Z",
    "createDate": "2020-07-11T18:09:31.016Z",
    "__v": 0
}

When specifying .get<Meeting>(`${this.apiUrl}${meetingId}`) you're letting TypeScript know that the get method will return a Meeting object which is not the case.当指定.get<Meeting>(`${this.apiUrl}${meetingId}`)你让 TypeScript 知道 get 方法将返回一个Meeting object ,但事实并非如此。 If you check the result of your method with data instanceof Meeting it will return false.如果您使用data instanceof Meeting检查您的方法的结果,它将返回 false。 You will need to create a meeting object and populate it with the data received from the request.您将需要创建一个会议 object 并使用从请求中收到的数据填充它。

The easiest way to do this without any libraries will probably be as follows.在没有任何库的情况下执行此操作的最简单方法可能如下。

export class Meeting {
  _id?: string;
  name: string;
  roomSid?: string;
  users: User[];
  contentList: any;

  constructor(data) {
    this._id = data._id;
    this.name = data.name;
    this.roomSid = data.roomSid;
    this.users = data.users.map(user => new User(user));
    this.contentList = data.contentList;
    // ...
  }
}

export class User {
  _id: string;
  firstName: string;
  lastName: string;
  dealerName: string;
  location: string;
  role: 'attendee' | 'host' | 'participant';
  videoServiceId: string;
  profilePic?: string;
  __v?: string;

  constructor(data) {
    this._id = data._id:
    this.firstName = data.firstName:
    // ...
  }

  get isHost(): boolean {
    return this.role === 'host';
  }

  get isAttendee(): boolean {
    return this.role === 'attendee';
  }

  get isParticipant(): boolean {
    return this.role === 'participant';
  }

  get isClient(): boolean {
    return this.isAttendee || this.isParticipant;
  }
}

function getMeeting(meetingId): Observable<Meeting> {
  this.httpClient.get<Meeting>(`${this.apiUrl}${meetingId}`)
    .pipe(
      catchError(this.handleError),
      map(meeting => new Meeting(meeting)),
    );
}

The downside of this approach is the DRYness as the property name is repeated three times.这种方法的缺点是 DRYness,因为属性名称重复了 3 次。 An alternative is solutions such as TypedJson which allow you to serialize and deserialze objects with help of decorators.另一种选择是诸如TypedJson 之类的解决方案,它允许您在装饰器的帮助下序列化和反序列化对象。 Quick example of a model in TypedJSON: TypedJSON 中 model 的快速示例:

@jsonObject
class Meeting {

    @jsonMember
    _id: string;
    
    @jsonArrayMember(User)
    users: Array<User>;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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