title: Angular Convert API JSON Response Object with Fields to Array
body: <p>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:</p>
  
  <blockquote>
    <p>Cannot read property 'data' of undefined</p>
  </blockquote>
  
  <p>Having researched for a while now and tried a number of different suggestions from very similar questions, the closest being <a href="https://stackoverflow.com/questions/39308423/how-to-convert-json-object-to-an-typescript-array">this one</a>, 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.</p>
  
  <p><strong>Model</strong></p>
  
  <pre><code>export class Site {
    elevation: number;
    id: number;
    latitude: number;
    longitude: number;
    name: string;
    region: string;
    unitaryAuthArea: string;
  }
  </code></pre>
  
  <p><strong>Service</strong></p>
  
  <pre><code>@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&lt;Site[]&gt; {
          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);
    }
  }
  </code></pre>
  
  <p><strong>Component</strong></p>
  
  <pre><code>  @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 =&gt; this.sites = sites,
              error =&gt;  this.errorMessage = &lt;any&gt;error);
    }
  };
  </code></pre>
  
  <p><strong>View</strong></p>
  
  <pre><code>&lt;h1&gt;
    {{title}}
  &lt;/h1&gt;
  
  &lt;div id="sites"&gt;
    &lt;ul&gt;
      &lt;li *ngFor="let site of sites"&gt;
        {{site.name}} ||| {{site.unitaryAuthArea}}
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>As always, all help greatly appreciated.</p>
  
  <p><strong>EDIT</strong>:  A snippet of the JSON, it has 4,000 location objects or so.</p>
  
  <pre><code>{
      "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"
          }]
      }
  }
  </code></pre>
  
  <p><strong>Update</strong> Developer Tools showing response</p>
  
  <p><a href="https://i.stack.imgur.com/Jq4J5.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Jq4J5.png" alt="enter image description here"></a></p>