简体   繁体   中英

How to map json into interface object in Angular

I am learning Angular. (Version 11).

I'm not quite sure what I am missing. I am calling an API from my service to get a JSON object and return it into the interface object that I created.

However when I look at the value country in the html it is not my country interface it is the full object that came from the api. (My interface should only have a subset of values).

Service:

  getCountry(): void {
    const name = this.route.snapshot.paramMap.get('name');
    this.countryService.getCountry(name)
      .subscribe(x => this.country = x);
  };

Component:

export class CountryDetailComponent implements OnInit {
  country: Country;
  
  constructor(
    private countryService: CountryService,
    private route: ActivatedRoute
  ) { }

  ngOnInit(): void {
    this.getCountry();
    const x = this.country;
  }

  getCountry(): void {
    const name = this.route.snapshot.paramMap.get('name');
    this.countryService.getCountry(name)
      .subscribe(x => this.country = x);
  };

Country:

export interface Country {
  name: string,
  alpha2Code: string,
  alpha3Code: string,
  capital: string,
  region: string,
  subregion: string,
  population: number,
  demonym: string,
  area: number,
  gini: number
  flag: string
}

component.html

{{country | json}}

API: https://restcountries.eu/rest/v2/name/aruba?fullText=true

Result from html:

[ { "name": "Aruba", "topLevelDomain": [ ".aw" ], "alpha2Code": "AW", "alpha3Code": "ABW", "callingCodes": [ "297" ], "capital": "Oranjestad", "altSpellings": [ "AW" ], "region": "Americas", "subregion": "Caribbean", "population": 107394, "latlng": [ 12.5, -69.96666666 ], "demonym": "Aruban", "area": 180, "gini": null, "timezones": [ "UTC-04:00" ], "borders": [], "nativeName": "Aruba", "numericCode": "533", "currencies": [ { "code": "AWG", "name": "Aruban florin", "symbol": "ƒ" } ], "languages": [ { "iso639_1": "nl", "iso639_2": "nld", "name": "Dutch", "nativeName": "Nederlands" }, { "iso639_1": "pa", "iso639_2": "pan", "name": "(Eastern) Punjabi", "nativeName": "ਪੰਜਾਬੀ" } ], "translations": { "de": "Aruba", "es": "Aruba", "fr": "Aruba", "ja": "アルバ", "it": "Aruba", "br": "Aruba", "pt": "Aruba", "nl": "Aruba", "hr": "Aruba", "fa": "آروبا" }, "flag": "https://restcountries.eu/data/abw.svg", "regionalBlocs": [], "cioc": "ARU" } ]

You're missing few fundamental concepts:

  1. The API returns an Array of countries( with only one value) so the variable to hold this value should be:

    this.countryService.getCountry(name).subscribe(x => this.country = x[0]);

  2. Interfaces are used for static type checking, at run time there is no interface because the code gets transpiled into Javascript and interface doesn't exist in JS. Interface is not meant to be used like the way you're using.

here's a good read: https://www.typescriptlang.org/docs/handbook/interfaces.html

  1. You need to create a class and assign the values manually if you want to keep subset of values.
 name: string;
 alpha2Code: string;
 alpha3Code: string;
 capital: string;
 region: string;
 subregion: string;
 population: number;
 demonym: string;
 area: number;
 gini: number;
 flag: string;

 constructor(d: any) {
   this.name = d.name;
   ...
 }
}

If you wish to strip out your additional properties, you need a class . An interface doesn't actually do anything. It's strictly a data contract or schema for a model. If you set something and there are additional properties, they will be set on the interface.

TypeScript Playground

class Country {
  name: string;
  alpha2Code: string;
  alpha3Code: string;
  capital: string;
  region: string;
  subregion: string;
  population: number;
  demonym: string;
  area: number;
  gini: number;
  flag: string;

  constructor(d: any) {
    this.name = d.name;
    this.alpha2Code = d.alpha2Code;
    ...
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM