HttpClient Angular 9 преобразование вложенного json во вложенный объект - PullRequest
0 голосов
/ 14 июля 2020

Я пытаюсь понять, есть ли более элегантный способ, кроме использования карты, для выполнения sh следующего:

У меня есть класс с массивом другого объекта. Итак, у моего объекта Meeting много пользователей:

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;
  }
}

Когда я делаю:

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

без использования карты для преобразования полученного результата из get, массив объектов User устанавливается неправильно . Мои геттеры не определены, если я не выполняю Object.assign (новый пользователь, пользователь). HttpGet просто возвращает Meeting как класс Meeting, только не объекты внутри.

Что-то мне не хватает, или это работает так, как задумано, и у меня нет другого выбора, кроме как использовать map (). Хотя я чувствую, что если у меня есть другой объект внутри моего класса User, все может стать немного запутаннее.

Для справки вот ответ от сервера:

{
    "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
}

1 Ответ

0 голосов
/ 14 июля 2020

При указании .get<Meeting>(`${this.apiUrl}${meetingId}`) вы даете TypeScript знать, что метод get вернет объект Meeting, что не так. Если вы проверите результат своего метода с помощью data instanceof Meeting, он вернет false. Вам нужно будет создать объект встречи и заполнить его данными, полученными из запроса.

Самый простой способ сделать это без каких-либо библиотек, вероятно, будет следующим.

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)),
    );
}

Обратной стороной этого подхода является СУХОСТЬ, поскольку имя свойства повторяется три раза. Альтернативой являются такие решения, как Typed Json, которые позволяют сериализовать и десериализовать объекты с помощью декораторов. Быстрый пример модели в набранном виде JSON:

@jsonObject
class Meeting {

    @jsonMember
    _id: string;
    
    @jsonArrayMember(User)
    users: Array<User>;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...