当前位置: 首页 > 知识库问答 >
问题:

通过Angular的HttpClient检索的映射/隐藏对象[副本]

华飞驰
2023-03-14

也许用一个例子来解释更好。

我有以下课程:

export class Foo {
    bar: string;

    doSomething() {
        // whatever
    }
}

以及以下提供商:

@Injectable()
export class FooProvider {

  constructor(private http: HttpClient) {

  }

  getFoos(): Observable<Foo[]> {
    return this.http.get<Foo[]>('/foos')
  }

}

当订阅< code>Observable时,我希望数据是< code>Foo对象的实际数组。但令我惊讶的是,数组中的对象是简单的javascript对象,只有数据,没有方法(实际上,当试图在其中任何一个对象中执行< code>doSomething()时,都会出现< code >不是函数错误)。

我能够做到这一点的唯一方法是像这样映射可观察量:

@Injectable()
export class FooProvider {

  constructor(private http: HttpClient) {

  }

  getFoos(): Observable<Foo[]> {
    return this.http.get<Foo[]>('/foos')
        .map(foos => {
            foos.map(foo => {
                let f = new Foo();
                Object.assign(f, foo);
                return f;
            };
        });
  }

}

问题是,我不想在每个提供商的每种方法中都这样做。看到执行转换的代码非常简单,我猜我错过了一些东西,但我无法在文档中找到它。

有人能帮我吗?

共有1个答案

郭凯
2023-03-14

就像@tos kv所说,您需要手动创建对象。尽管标记为重复的两个答案都可以解决OP,但我想添加这个答案,因为我通常会做一些不同的事情。

所有答案都使用Object.assign(f, foo);将属性从普通对象复制到类实例。没关系,但在我的情况下,我希望对应用程序中使用的属性的名称有更多的控制权。为什么?所以如果api返回一个属性username,但随后它被更改并且相同属性的名称是fullname,我不想更新应用程序中使用该属性的所有页面。

因此,我通常会创建一些静态方法,如下所示:

export class Foo {
    bar: string;

    doSomething() {
        // whatever
    }

    // Static method that creates the instance from 
    // a plain javascript object
    public static fromObject(object: any): Foo {
        let instance = new Foo();

        if(!object) return instance;

        // Here you can decide which name should each property have. 
        // If the API changes in the future, you would only need to 
        // modify a single line of code and that's it. You could also
        // modify each property and give it a specific format if you want
        instance.bar = object.bar;

        // more properties ...

        return instance;
    }

    // Static method that creates a list of instances from a list 
    // of plain javascript objects
    public static fromJsonList(objectList: Array<any>): Array<Foo> {
        let instances = new Array<Foo>();

        if (!objectList || (objectList && objectList.length === 0)) return Foo;

        objectList.forEach(object => instances.push(Foo.fromJson(object)));

        return instances;
    }
}

然后,我在服务中使用它:

getFoos(): Observable<Foo[]> {
    return this.http.get<Foo[]>('/foos').map(response => Foo.fromJsonList(response));
}

因此,通过做这样的事情:

  1. 如果任何属性的名称发生更改,则需要更改一行代码,每个页面仍将正常工作。
  2. 与应如何创建每个实例相关的所有“逻辑”都封装在模型中,而不是在服务中添加部分实例。
 类似资料:
  • 我正在从React中的外部api接收数据 我有一个目标 我试图通过它进行映射,以便能够渲染数据,即它在屏幕上显示的“bitfinex:1.2、blockfi:2.3等” 但是我得到了一个错误,说它不是一个函数。 我做错了什么?

  • 问题内容: 假设此JSON对象: 可以像这样检索“ set2”属性: 有没有一种方法可以通过索引检索“ set2”属性?它是JSON对象的第二个属性。这是行不通的(当然): 因此,假设我要检索JSON对象的第二个属性,但我不知道它的名称-那么我该怎么做? 更新: 是的,我知道对象是无序属性的集合。但是我不认为浏览器会干扰JSON文字/字符串定义的“原始”顺序。 问题答案: JavaScript中的

  • 我不想映射变量。是否有任何方法可以配置映射器,使其忽略此字段? 我知道我可以编写自定义数据映射器或使用流式API,但我想知道是否可以通过配置来实现?

  • 我正在使用DTO对象从spring rest控制器中的@RequestBody中检索信息,并在json响应中使用相同的DTO对象。我想完全隐藏一些字段不让响应。 我尝试了,它为未映射的属性返回null,但我的问题是: null FieldBonlyOrderToOrderToMapper 将返回一个OrderDto对象,该对象没有名为(otherFiledA)的字段

  • 我希望在我的dao对象中有这样的方法 但我得到了错误 错误:不确定如何将游标转换为此方法的返回类型public abstract java。util。地图 是否可以将其更改为工作版本? 因此,返回的类型可能不同,但主要条件是 数据库中只能有一个查询 我希望避免额外的代码,比如只为这个方法创建额外的数据结构

  • 我有一个对象,我正试图映射到。现在这个有一个名为的枚举,其中包含一些值。我想使用将它们映射到中的其他枚举值。以下是我到目前为止的代码: 当我尝试编译它时,我得到了错误: