Búsqueda de sitios web

angularjs - llamada HTTP observable en Angular, mapear la respuesta a la interfaz


Tengo una función que llama a una API REST así:

getProducts(category: string): Observable<IProduct[]> {
    let url = `/rest/getproducts?category=${category}`;
    return this._http.get<IProduct[]>(url);
  }

La respuesta del servicio se ve así:

[
  {
    "ProductId": 1,
    "CategoryType": "XC",
    "Name": "Prod A"
  },
  {
    "ProductId": 2,
    "CategoryType": "XY",
    "Name": "Prod B"
  },
]

Mi modelo se ve así:

export interface IProduct {
    id: string;
    type: string;
    name: string;
}

¿Hay una manera de mapear la respuesta a mi modelo de forma sencilla? ¿Debería usar la función map? Sé que podría cambiar el modelo para adaptarlo a la respuesta, pero preferiría encajar la respuesta en mi modelo (el ejemplo está simplificado).

Respuesta #1

La solución más simple sería usar una interfaz que tenga la forma de los datos reales del servidor. Menos problemas, sin mapeo, menos mantenimiento.

Incluso si quieres hacer algo de mapeo, todavía sería una buena idea tener una interfaz para el objeto del servidor, para que el mapeo se pueda hacer de manera segura:

interface IServerProduct {
    "ProductId": number;
    "CategoryType": string;
    "Name": string;
}

export interface IProduct {
    id: string;
    type: string;
    name: string;
}

getProducts(category: string): Observable<IProduct[]> {
    let url = `/rest/getproducts?category=${category}`;
    return this._http.get<IServerProduct[]>(url).pipe(
        map(o => o.map((sp): IProduct => ({ // IProduct specified here ensures we get excess property checks
            id: sp.ProductId + '', // number in server interface, map to string 
            name: sp.Name,
            type: sp.CategoryType,
            typeMisaken: sp.CategoryType, // error here
        })))
    );
}

Respuesta #2

Tu interfaz debería verse como la siguiente, si no deseas hacer ningún cambio en el código, puedes revisarlo aquí json2ts

declare module namespace {
    export interface IProduct {
        ProductId: number;
        CategoryType: string;
        Name: string;
    }
}

de lo contrario, podrías usar la función array.map y generar tu array por tu cuenta.

Artículos relacionados