【问题标题】:How can I make sure my json structure maps to my interface?如何确保我的 json 结构映射到我的界面?
【发布时间】:2018-09-02 09:12:53
【问题描述】:

所以,我的产品信息 api 的预期 json 响应如下所示:

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

对于这个特定的api调用,我最感兴趣的是productDetails信息和errorStatus。我想根据上面的json响应创建一个productDetails对象,所以我创建了两个接口,一个用于product,一个用于productdetails。

这是我的界面:

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

在我的一项服务中,我有这个电话:

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

在我的一个组件中,我调用了该服务:

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

我的问题是,这是确保我在代码中使用的对象与 json 响应数据匹配的正确方法吗?它如何知道在我的界面中将 _productSkuKey 与 productSkuKey 映射?

【问题讨论】:

  • 为什么您的属性名称前面有下划线?删除这些将解决您遇到的问题。
  • 这就是 json 响应的样子。我应该在接口属性中添加下划线以匹配 json 对象吗?
  • 这取决于你。您可以更改products 接口以匹配响应,也可以重命名所有道具以匹配接口。
  • 如果您不想在界面中使用下划线但必须将其保留在服务中,您可以调用 map (this.http.get&lt;IProduct[]&gt;(this.products).map (p =&gt; ..) 并自己进行映射

标签: angular typescript


【解决方案1】:

接口的结构和 JSON 的结构必须相同,这意味着属性应该具有完全相同的名称。

因此您必须在接口中添加下划线,或者将它们从服务中删除。

但是,无法确保您的界面与服务中的 JSON 匹配。通过定义一个接口,你告诉 TypeScript 你期望。它不会阻止您收到不同的东西,因为类型信息在编译后会消失

【讨论】:

    【解决方案2】:

    如果您出于某种原因不想使用下划线更改界面道具,则可以使用 Interface 而不是 Class 像这样:

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

    将返回:

    SomeClass {productDepartment: 12, productClass: 34}
    

    CODE EXAMPLE

    为您服务:

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

    【讨论】:

    • 或更短:map(prodRes =&gt; prodRes.map(prod =&gt; new Product(prod)));
    猜你喜欢
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多