简体   繁体   English

将JSON转换为复杂类型

[英]Casting JSON to complex types

I am trying to cast my http.get response to actual object -> in my specific case array of complex objects. 我正在尝试将我的http.get响应http.get为实际对象->在特定情况下的复杂对象数组中。

In a normal scenario, where you don't need any specific casting, you could do the following (simplified): 在正常情况下,不需要任何特定的转换,则可以执行以下操作(简化):

return this.httpClient.get(api, this._options_get)
  .pipe(
    map((response: any) => {
      return response.value as NewProduct[];
    })
  );

As my need is to actually cast this to an object, I have created this static method which does that: 因为我需要将其实际转换为对象,所以我创建了该静态方法来执行此操作:

static toProduct(otherProduct: any): NewProduct {
    let item = new NewProduct();

    Object.keys(otherProduct).forEach(prop => {
        if (typeof otherProduct[prop] === "object" && otherProduct[prop]) {
            if (!item.hasOwnProperty(prop))
                item[prop] = otherProduct[prop];
            Object.assign(item[prop], otherProduct[prop]);
        }
        else
            item[prop] = otherProduct[prop];
    })

    return item;
}

Under Object.assign I am taking already existing object which was initialized under first line and I am simply copying all the properties from the otherProduct to it. Object.assign我要获取已存在的对象,该对象已在第一行下初始化,并且我只是将所有属性从otherProduct复制到该对象。 However I start to face problem when it comes to array of objects. 但是,当涉及对象数组时,我开始面临问题。 Example (with simplified class): 示例(具有简化的类):

export class Person {
    name:string;
    age:number;
    addresses:Address[] = [];
}
export class Address {
    street:string;
    city:string;
    fullAddress() : string { return this.street + this.city; }
}

As soon as I have this sort of array, I don't have any initial object in item . 一旦有了这种数组, item就没有任何初始对象了。 This means that there is no initial constructor of a class which results in simple Object . 这意味着不存在导致简单Object的类的初始构造函数。 This is no error for JavaScript or TypeScript; 对于JavaScript或TypeScript,这不是错误; however when I am trying to access internal method of a class (in our simplified case fullAddress() , I won't be able to. 但是,当我尝试访问类的内部方法(在我们简化的情况下, fullAddress() ,我将无法访问)。

The reason why I need that is that I am overriding toString() method on my sub-classes, which is necessary for MatTableDataSource when you use the filter method (which works with strings). 我之所以需MatTableDataSource ,是因为我在子类上覆盖了toString()方法,这在使用filter方法(适用于字符串)时对于MatTableDataSource是必需的。

Is there a way how to retrieve elements from http.get() and properly map results to typed objects? 有没有办法从http.get()检索元素并将结果正确映射到类型化的对象?

You're being too generic. 你太普通了。 You're creating objects of objects, not objects of Product with children of Addresses. 您正在创建对象的对象,而不是具有地址子代的Product对象。

If you want to create a new product you're going to have to understand the relationship between the api's results and the data you want in the UI. 如果要创建新产品,则必须了解api的结果与UI中所需数据之间的关系。

Because you're using classes and not interfaces and want to inherit the functions, the only way to get new Addresses into the new object is with the new keyword. 因为您使用的是类而不是接口,并且想要继承函数,所以将新地址放入新对象的唯一方法是使用new关键字。

And you'll have to loop through. 而且,您必须循环遍历。 You're not going to find a shortcut for this. 您不会为此找到捷径。 You're going to need to loop through the data and transform it. 您将需要遍历数据并对其进行转换。 If your api is giving you an ApiPerson then you'll want to do something like this: 如果您的api为您提供了ApiPerson,则您需要执行以下操作:

const addresses = apiPerson.addresses.map((apiAddress) => {
    const address = new Address();
    // map properties of apiAddress to address...
    return address;
});

Now that you have the addresses , you can map the apiPerson to a new Person() 's properties and then set the newPerson.addresses = address . 现在有了addresses ,您可以将apiPerson映射到new Person()的属性,然后设置newPerson.addresses = address

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM