Angular Convert API JSON Response Object with Fields to Array

13,964

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 || [];
}
Share:
13,964
K7Buoy
Author by

K7Buoy

Updated on June 04, 2022

Comments

  • K7Buoy
    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

    enter image description here