Angular: как сопоставить результат JSON из запроса HttpClient с экземплярами класса?

У меня есть следующий код, который кажется неправильным:

public search(searchString: string): Observable<Array<ClientSearchResult>> {
    let params = new HttpParams().set('searchString', searchString);

    return this.http
        .get<Array<ClientSearchResult>>(this.searchUrl, { params: params })
        .map((results: ClientSearchResult[]) => results.map((r: ClientSearchResult) => new ClientSearchResult(r)));
}

Я знаю, что API возвращает объект JSON, который не совпадает с экземпляром моего класса TypeScript. Однако я хочу использовать свойства, определенные в классе TypeScript.

Есть ли лучший способ сопоставить массив, полученный из моего вызова API, с массивом, который на самом деле состоит из экземпляров ClientSearchResult?

Вот объект ClientSearchResult:

import { Name } from './name';

export class ClientSearchResult {
    public id: string;
    public name: Name;
    public dateOfBirth: Date;
    public socialSecurityNumber: string;

    public get summary(): string {
        let result: string = `${this.name}`;

        if (this.dateOfBirth)
            result += ` | ${this.dateOfBirth.toLocaleDateString()}`;

        return result;
    }

    constructor(source: ClientSearchResult) {
        this.id = source.id;
        this.name = new Name(source.name);
        this.dateOfBirth = source.dateOfBirth? new Date(source.dateOfBirth) : undefined;
        this.socialSecurityNumber = source.socialSecurityNumber;
    }

    public toString(): string {
        return this.summary;
    }
}

person mlindegarde    schedule 09.10.2017    source источник
comment
Вы можете использовать Object.assign(new ClientSearchResult(), decodedJsonObject), если вы не хотите вручную устанавливать многие свойства, но это более или менее все.   -  person martin    schedule 09.10.2017
comment
не могли бы вы показать нам конструктор ClientSearchResult ? возможно, «новый ClientSearchResult(r)» — это не способ применить преобразование к экземпляру ClientSearchResult.   -  person Luillyfe    schedule 10.10.2017
comment
@Luillyfe Я обновил вопрос.   -  person mlindegarde    schedule 10.10.2017


Ответы (3)


Мы используем замечательную библиотеку для сопоставления json с объектами машинописного текста. https://github.com/shakilsiraj/json-object-mapper

json-object-mapper зависит от библиотеки Reflect-Metadata, поскольку он использует декораторы для сериализации и десериализации данных.

person artonio    schedule 19.02.2018

Как вариант, вы можете попробовать оператор TypeScript as, чтобы привести ваш ответ API к типу ClientSearchResult.

import { Http, Response } from '@angular/http';

public search(searchString: string): Observable<ClientSearchResult[]> {
    const params = new HttpParams().set('searchString', searchString);
    return this.http.get(this.searchUrl, { params: params })
        .map((results: Response) => results.json() as ClientSearchResult[]);
}

Этот подход требует, чтобы ваш класс модели использовался в качестве интерфейса или просто был интерфейсом:

interface ClientSearchResult {
  id: number;
  // etc
}
person dhilt    schedule 09.10.2017
comment
Спасибо за предложение. Однако я пытаюсь использовать новый HttpClient вместо Http. HttpClient дает мне типизированный массив, а не Response. Я посмотрю на оператора as и посмотрю, смогу ли я что-нибудь с этим сделать. - person mlindegarde; 10.10.2017

Я использовал эту очень хорошую (и актуальную на момент публикации) библиотеку:

https://www.npmjs.com/package/class-transformer

Он может обрабатывать очень сложные случаи с вложенными классами и многое другое.

person AsGoodAsItGets    schedule 13.11.2019