有没有办法在使用可观察对象时将复杂的 json 数据映射到打字稿中的接口?

Is there a way to map complex json data onto interfaces in typescript while using observables?

我正在尝试制作简单的网络新闻 reader,主要基于 google 新闻 api (https://newsapi.org/s/google-news-api)。我已经像往常一样完成了所有服务、模型等工作,但我在将数据映射到具体接口时遇到了问题。 Google api returns 在端点之一 ('top-headlines') 上,数据格式如下:

{
    "status": "ok",
    "totalResults": 38,
    "articles": [
       {
       "source": {
            "id": "the-new-york-times",
            "name": "The New York Times"
       },
      "author": null,
      "title": "Hong Kong Protesters Clash with Police Amid Fears of Mob 
       Violence - The New York Times",
      "description": "some description",
      "url": "https://www.nytimes.com/2019/08/11/world/asia/hong-kong- 
       protest.html",
      "urlToImage": 
      "https://static01.nyt.com/images/2019/08/11/world/11hongkong15/
       11hongkong15-facebookJumbo.jpg",
      "publishedAt": "2019-08-11T11:19:03Z",
      "content": "some content… [+751 chars]"
       },
      (...and many many more articles)
    ]
}

我只需要文章。我知道如果我从 api 中获取这些数据,我可以调用 myvariablename.articles,但这对我来说似乎不正确。

我首先尝试使用 rxjs 映射方法进行映射。但是我在控制台中收到错误消息,指出 Articles 模型中没有 属性 篇文章。所以我在响应模型(接口)中准备了响应模型和嵌套文章 属性。我得到了完全相同的错误。我在想,也许在方法 Observable 中定义有一些问题,所以我切换到 Response 但没有运气,现在我正在订阅和使用服务方法的组件出现错误,它说: "Type Response[] is not assignable to type Article[]"

top-news.service.ts

(...all imports)

export class TopNewsService {

(... ommited defining of variables like url etc.)

  public getAll(): Observable<Response[]> {
    return this.httpClient
      .get<Response[]>(`${this.url}/${this.endpoint}?country=us&apiKey=${this.token}`)
      .pipe(
        map(response => response.articles),
        catchError(this.handleError)
      );
  }
(...error handling)
}

article.ts

export interface Article {
  source: {
    id: string;
    name: string;
  };
  author: string;
  title: string;
  description: string;
  url: string;
  urlToImage: string;
  publishedAt: string;
  content: string;
}

response.ts

import { Article } from './article';

export interface Response {
  status: string;
  totalResults: number;
  articles: Article;
}

头条新闻-component.ts

(...all imports)

export class TopNewsComponent implements OnInit {

  articles: Article[];

  constructor(private http: HttpClient, private topNewsService: TopNewsService) { }

  ngOnInit() {
    this.getAllProjects();
  }

  getAllProjects() {
    this.topNewsService.getAll().subscribe(data => {
      this.articles = data;
      console.log(this.articles)
    },
      (err: string) => {
        alert(err);
      });
  }
}

我希望能够在服务中映射数据,return 仅在文章中映射数据,然后(如果可能的话)在我的组件中获取这些数据并将其分配给定义类型为 Article[] 的已创建变量.

您正在使用

this.httpClient.get<Response[]>

这意味着你期望Google到return一个响应数组。但这不是 return 的意思。它 return 是一个 Response。所以应该是

this.httpClient.get<Response>

并且由于您(尝试)将此响应映射到一系列文章,因此可以观察到您的服务 returns 是 Observable<Article[]>,而不是 Observable<Response[]>。所以应该是

public getAll(): Observable<Article[]> {

这个界面

export interface Response {
  status: string;
  totalResults: number;
  articles: Article;
}

也是错误的。回复不包含一篇文章。它包含一系列文章。看看 JSON:

{
  "status": "ok", // one status string
  "totalResults": 38, // one totalResults number
  "articles": [ // an **array** of articles
    ..
  ]
}

所以应该是

export interface Response {
  status: string;
  totalResults: number;
  articles: Article[];
}