我正在尝试通过外部 api 从 json 数据中获取键值对并使用 angular 和 typescript 显示它。我怎样才能做到这一点?

Posted

技术标签:

【中文标题】我正在尝试通过外部 api 从 json 数据中获取键值对并使用 angular 和 typescript 显示它。我怎样才能做到这一点?【英文标题】:I'm Trying to get key value pairs from json data via an external api and display it using angular and typescript. How can I achieve this? 【发布时间】:2020-08-14 00:54:44 【问题描述】:

我想从我的 api 获取结果对象中的每个键值对以显示在我的前端。即(类别、类型、难度、问题正确答案)我已经正确设置了服务和组件,我需要做的就是获取 json 并显示每一对。方法名称称为 fetchQuestions,如下所示。我只需像 fetchPeople 一样简单地调用它,就能够成功获取数据,但 json 格式不一样,所以它不显示。然后我尝试了其他方法,但这也不起作用。我怎样才能显示这个?

人员.服务

 import  Injectable  from '@angular/core';
 import  Observable  from  'rxjs/Observable';
 import  HttpClient  from '@angular/common/http';
 import  map  from 'rxjs/operators';

 @Injectable(
 providedIn: 'root'
 )
 export class PeopleService 

 constructor(private http: HttpClient)  


//this works like a charm as it is just a simple array

fetchPeople(): Observable <Object> 
return this.http.get('/assets/data/people.json')





// this doesn't work as the json from the api below is in a different 
  // json format. Plus I need to return all value pairs

fetchQuestions(): Observable <Object> 
return this.http.get('https://opentdb.com/api.php? 
 amount=10&difficulty=hard&type=boolean').map(res => 
res.json().results).subscribe(data => 
console.log(data););
    
  

API https://opentdb.com/api.php?amount=10&difficulty=hard&type=boolean

   
   "response_code": 0,
   "results": [
   
   "category": "Vehicles",
   "type": "boolean",
   "difficulty": "hard",
   "question": "In 1993 Swedish car manufacturer Saab experimented 
   with replacing the steering wheel with a joystick in a Saab 9000.",
   "correct_answer": "True",
   "incorrect_answers": [
    "False"
   ]
   ,
   
  "category": "History",
  "type": "boolean",
  "difficulty": "hard",
  "question": "Japan was part of the Allied Powers during World War 
  I.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
  ,
  
  "category": "History",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The Kingdom of Prussia briefly held land in Estonia.",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
  ,
  
  "category": "Science: Mathematics",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The binary number &quot;101001101&quot; is equivalent 
  to the Decimal number &quot;334&quot;",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
  ,
  
  "category": "Entertainment: Video Games",
  "type": "boolean",
  "difficulty": "hard",
  "question": "TF2: Sentry rocket damage falloff is calculated based 
 on the distance between the sentry and the enemy, not the engineer 
  and the enemy",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
 ,
  
  "category": "Entertainment: Video Games",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The names of Roxas&#039;s Keyblades in Kingdom Hearts 
  are &quot;Oathkeeper&quot; and &quot;Oblivion&quot;.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
,

  "category": "Entertainment: Music",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The band STRFKR was also briefly known as Pyramiddd.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
,

  "category": "Entertainment: Books",
  "type": "boolean",
  "difficulty": "hard",
  "question": "Harry Potter was born on July 31st, 1980.",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
  ]
,

  "category": "Entertainment: Japanese Anime & Manga",
  "type": "boolean",
  "difficulty": "hard",
  "question": "Druid is a mage class in &quot;Log Horizon&quot;.",
  "correct_answer": "False",
  "incorrect_answers": [
    "True"
  ]
,

  "category": "Geography",
  "type": "boolean",
  "difficulty": "hard",
  "question": "The two largest ethnic groups of Belgium are Flemish and Walloon. ",
  "correct_answer": "True",
  "incorrect_answers": [
    "False"
     ]
   
 ]

人物.page.ts

 import  Component, OnInit  from '@angular/core';
 import  PeopleService  from './../../providers/people.service'
 @Component(
 selector: 'app-people',
 templateUrl: './people.page.html',
 styleUrls: ['./people.page.scss'],
 )
 export class PeoplePage implements OnInit 

 people$;
 results$;
 constructor(private peopleService:PeopleService)  

 fetchPeople()
 this.people$ = this.peopleService.fetchPeople();
 
 fetchQuestions()
  this.results$ = this.peopleService.fetchQuestions()
 




  ngOnInit() 
  

 

人物.page.html

   <ion-toolbar>
   <ion-title>people</ion-title>
   </ion-toolbar>
   </ion-header>
   <ion-button (click) ="fetchPeople()"  color="primary">Primary</ion- 
   button>

   <ion-list>
   <ion-item *ngFor="let person of people$ | async">person.name. 
   </ion-item>
   </ion-list>
   <ion-button (click) ="fetchQuestions()"  
   color="primary">Secondary</ion-button>
   <ion-list>
            <ion-item *ngFor="let result of results$ | async">. 
             result.category</ion-item>
             <ion-item *ngFor="let result of results$ | async"> 
            result.questions</ion-item>
           <ion-item *ngFor="let result of results$ | async"> 
           result.difficulty</ion-item>
           <ion-item *ngFor="let result of results$ | async"> 
            result.correct_answer</ion-item>
   </ion-list>
  <ion-content>
 <ion-button color="primary">Primary</ion-button>
 </ion-content>

【问题讨论】:

【参考方案1】:

HTTP GET 是一个冷的 observable。因此,每个async 都会触发一个单独的请求。此外,您实际上并没有从 fetchQuestions() 函数返回 observable。应删除订阅。

您也可以使用 Angular HttpParams 设置查询参数并以 Angular 方式执行操作。

试试下面的

服务

import  HttpClient, HttpParams  from '@angular/common/http';

fetchQuestions(): Observable<any> 
  const params = new HttpParams()
    .set('amount', '10')
    .set('difficulty', 'hard')
    .set('type', 'boolean');  
  return this.http.get('https://opentdb.com/api.php',  params: params )
    .pipe(map(res => res.results));

模板

<ng-container *ngFor="let result of results$ | async">
  <ion-list>
    <ion-item>result.category</ion-item>
    <ion-item>result.question</ion-item>
    <ion-item>result.difficulty</ion-item>
    <ion-item>result.correct_answer</ion-item>
  </ion-list>
</ng-container>

我还注意到一个小字体。 result.questions 实际上应该是 result.question

关于热与冷可观察的更多细节:https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html

工作示例:Stackblitz

【讨论】:

我在尝试 rc/app/providers/people.service.ts:29:26 时收到此错误 - 错误 TS2339:“对象”类型上不存在属性“json”。 29 .pipe(map(res => res.json().results)); 是的,在最新版本中不需要.json()。试试res =&gt; res.results。我已经更新了答案。 随着更新,我现在得到的属性“结果”在“对象”类型上不存在。 29 .pipe(map(res => res.results)); 我在回答中将函数的返回类型更改为Observable&lt;any&gt;。你还在用Observable&lt;Object&gt;吗?如果是这样,请尝试使用Observable&lt;any&gt; 我正在使用 Observable

以上是关于我正在尝试通过外部 api 从 json 数据中获取键值对并使用 angular 和 typescript 显示它。我怎样才能做到这一点?的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 从外部 api 读取 json 数据

Express 和 Nodejs:调用外部 API 的最佳方式

如何从 JSON 获取数据以在 PrimeNG 折线图中使用?

iOS:从 Alamofire 解析的 SwiftyJSON 是一个数组。尝试解析时为空

Django rest框架拉入外部json数据

通过 API-KEY 使用来自外部 API 的数据的 Alexa 技能