0

So, my expected json response from my product information api looks like this:

{
    _productDepartment : null,
    _productClass : null,
    _productMaterial : null,
    _productStyle : null,
    _productDetails :
    {
        _productSkuKey : 800,
        _description : "Product Description",
        _collection : "Collection1",
        _department : 200,
        _productSize : "Size1",
        _productClass : 45,
        _productStyle : 1234,
        _material : "Product Material",
        _price : 100.00,
        _mediaFileName : "XYZ"
    },
    _products : null,
    _errorDetails :
    {
        _message : "success",
        _status : 200
    }
}

For this specific api call, I'm mostly interested in the productDetails information and errorStatus. I want to create a productDetails object based on the json response above, so I created two interfaces, one for product and one for productdetails.

Here are my interfaces:

//product.ts
import { IProductDetails } from './productDetails';

export interface IProduct {

    productDepartment: string;
    productClass: string;
    productMaterial: string;
    productStyle: string;
    productDetails: IProductDetails;
    products: null;
    errorDetails: string;

}

//productDetails.ts
export interface IProductDetails {
    productSkuKey: number;
    description: string;
    collection: string;
    department: number;
    productSize: string;
    productClass: string;
    productStyle: number;
    material: string;
    price: string;
    mediaFileName: string;
}

In one of my services, I have this call:

getProducts(storeId: string, productSKU: string) {
    this.products = this.baseUrl + '/products/' + storeId + '/' + productSKU;
    return this.http.get<IProduct[]>(this.products).catch(this.errorHandler);
  }

and in one of my components, I call the service:

this._transactionService.getProduct('98', '343').subscribe(data => this.products = data._productDetails);

My question is, is this the right approach for making sure the object I use in my code matches the json response data? How does it know to map _productSkuKey with productSkuKey in my interface?

Euridice01
  • 2,510
  • 11
  • 44
  • 76
  • 1
    Why do you have the leading underscore on your property names? Removing those will fix the problem you are having. – Sara M Mar 23 '18 at 16:10
  • That's just how the json response looks like. Should I add the underscores to my interface properties to match the json object? – Euridice01 Mar 23 '18 at 16:21
  • It's up to you. You can either change `products` interface to match the response, or you can rename all props to match the interface. – Estus Flask Mar 23 '18 at 16:25
  • You can call `map` `(this.http.get(this.products).map (p => ..)` and do you own mapping if you don't want the underscore in your interface but have to leave it in your service – David Mar 23 '18 at 17:49

2 Answers2

2

The structure of your interface and the structure of your JSON must be equivalent, meaning that the properties should have the same exact names.

So you have to add the underscores to the interfaces, or remove them from the service.

However, there is no way to make sure that your interface matches the JSON from the service. By defining an interface you're telling TypeScript what you expect. It doesn't prevent you from receiving something different, as type information disappears after compilation

Oscar Paz
  • 18,084
  • 3
  • 27
  • 42
1

If you don't want to change interface props with underscore for some reason, instead of Interface you can you Class something like this:

export class SomeClass {
  productDepartment = 0;
  productClass = 0;

  constructor(data: any) {
    for (let prop of Object.keys(data)) {

      if (this.hasOwnProperty(prop)) {
        this[prop] = data[prop];
      } else {
        let gProp = prop.substring(1);
        if (this.hasOwnProperty(gProp)) {
          this[gProp] = data[prop];
        }
      }
    }
  }
}
...
 this.data = new SomeClass({
  _productDepartment: 12,
  _productClass: 34
});

will return:

SomeClass {productDepartment: 12, productClass: 34}

CODE EXAMPLE

In you service:

getProducts(storeId: string, productSKU: string) {
    this.products = this.baseUrl + '/products/' + storeId + '/' + productSKU;
    return this.http.get<Product[]>(this.products)
     .map(prodRes => prodRes.map(prod => new Product(prod)))
     .catch(this.errorHandler);
  }
Yerkon
  • 4,548
  • 1
  • 18
  • 30