Angular Convert API JSON Response Object with Fields to Array
There is no res.json().Location
but res.json().Locations
(note the "s") and furthermore, there is no object data
that you are trying to extract from the response, but Location
. So if you want to extract the array, your extractData
should look like this:
private extractData(res: Response){
let body = res.json().Locations.Location;
return body || [];
}
K7Buoy
Updated on June 04, 2022Comments
-
K7Buoy almost 2 years
Learning Angular and having been through the heroes tutorial I wanted to try a real world http request so I am hitting the MetOffice DataPoint API. A JSON object is being returned that won't currently convert to an array for me to loop through. I am getting the following error:
Cannot read property 'data' of undefined
Having researched for a while now and tried a number of different suggestions from very similar questions, the closest being this one, below are the various things I have tried with comments on what failed at each attempt. I have confirmed in JSONLint that the JSON is valid.
Model
export class Site { elevation: number; id: number; latitude: number; longitude: number; name: string; region: string; unitaryAuthArea: string; }
Service
@Injectable() export class MetOfficeService { private testUrl = 'http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/sitelist?key=xxx'; constructor(private http: Http) { } getSites(): Observable<Site[]> { return this.http.get(this.testUrl) .map(this.extractData) .catch(this.handleError); } private extractData(res: Response){ let body = res.json().Location; Cannot read property 'data' of undefined //let body = res.json()['Location']; Cannot read property 'data' of undefined //let temp = res.json()['Location']; //let body = JSON.parse(temp); Unexpected token o on line 1 ... this is because of unrequired parsing i have discovered //return body || { }; this is nonsense. return body.data || { }; } private handleError (error: Response | any) { // In a real world app, you might use a remote logging infrastructure let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = body.error || JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''} ${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return Observable.throw(errMsg); } }
Component
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [MetOfficeService] }) export class AppComponent implements OnInit { title = 'test!'; errorMessage: string; sites: Site[]; ngOnInit() { this.getSites(); } constructor(private moService: MetOfficeService) { } getSites(){ this.moService.getSites() .subscribe( sites => this.sites = sites, error => this.errorMessage = <any>error); } };
View
<h1> {{title}} </h1> <div id="sites"> <ul> <li *ngFor="let site of sites"> {{site.name}} ||| {{site.unitaryAuthArea}} </li> </ul> </div>
As always, all help greatly appreciated.
EDIT: A snippet of the JSON, it has 4,000 location objects or so.
{ "Locations": { "Location": [{ "elevation": "7.0", "id": "3066", "latitude": "57.6494", "longitude": "-3.5606", "name": "Kinloss", "region": "gr", "unitaryAuthArea": "Moray" }, { "elevation": "6.0", "id": "3068", "latitude": "57.712", "longitude": "-3.322", "obsSource": "LNDSYN", "name": "Lossiemouth", "region": "gr", "unitaryAuthArea": "Moray" }, { "elevation": "36.0", "id": "3075", "latitude": "58.454", "longitude": "-3.089", "obsSource": "LNDSYN", "name": "Wick John O Groats Airport", "region": "he", "unitaryAuthArea": "Highland" }] } }
Update Developer Tools showing response