mirror of
https://gitlab.com/restcountries/restcountries.git
synced 2026-03-31 15:07:46 +01:00
Finnishing V4 as Preview
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package com.restcountries.controller;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.restcountries.domain.ICountryRestSymbols;
|
||||
import com.restcountries.domain.v4.Country;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ControllerV4Helper {
|
||||
|
||||
protected Object checkFieldsAndParseCountries(Optional<String> fields, Set<Country> countries) {
|
||||
if (fields.isPresent()) {
|
||||
return parsedCountries(countries, fields.get());
|
||||
} else {
|
||||
return parsedCountries(countries, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object checkFieldsAndParseCountry(Set<Country> countries, Optional<String> fields) {
|
||||
if (fields.isPresent()) {
|
||||
return parsedCountry(countries, fields.get());
|
||||
} else {
|
||||
return parsedCountry(countries, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected Object parsedCountries(Set<Country> countries, String excludedFields) {
|
||||
if (excludedFields == null || excludedFields.isEmpty()) {
|
||||
return countries;
|
||||
} else {
|
||||
return getCountriesJson(countries,
|
||||
Arrays.asList(excludedFields.split(ICountryRestSymbols.COLON)));
|
||||
}
|
||||
}
|
||||
|
||||
protected static Object parsedCountry(Set<Country> countries, String fields) {
|
||||
if (fields == null || fields.isEmpty()) {
|
||||
return countries;
|
||||
} else {
|
||||
StringBuilder result = new StringBuilder();
|
||||
countries.forEach(country -> result.append(
|
||||
getCountryJson(country, Arrays.asList(fields.split(ICountryRestSymbols.COLON)))));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCountryJson(Country country, List<String> fields) {
|
||||
var gson = new Gson();
|
||||
var jsonObject = JsonParser.parseString(gson.toJson(country)).getAsJsonObject();
|
||||
List<String> excludedFields = new ArrayList<>(Arrays.asList(V4_COUNTRY_FIELDS));
|
||||
excludedFields.removeAll(fields);
|
||||
excludedFields.forEach(jsonObject::remove);
|
||||
return jsonObject.toString();
|
||||
}
|
||||
|
||||
private String getCountriesJson(Set<Country> countries, List<String> fields) {
|
||||
var gson = new Gson();
|
||||
var jsonArray = JsonParser.parseString(gson.toJson(countries)).getAsJsonArray();
|
||||
var resultArray = new JsonArray();
|
||||
jsonArray.forEach(element -> {
|
||||
var jsonObject = (JsonObject) element;
|
||||
var excludedFields = getExcludedFields(fields);
|
||||
excludedFields.forEach(jsonObject::remove);
|
||||
resultArray.add(jsonObject);
|
||||
});
|
||||
return resultArray.toString();
|
||||
}
|
||||
|
||||
private List<String> getExcludedFields(List<String> fields) {
|
||||
List<String> excludedFields = new ArrayList<>(Arrays.asList(V4_COUNTRY_FIELDS));
|
||||
excludedFields.removeAll(fields);
|
||||
return excludedFields;
|
||||
}
|
||||
|
||||
boolean isEmpty(String value) {
|
||||
return value == null || value.isEmpty();
|
||||
}
|
||||
|
||||
protected static final String[] V4_COUNTRY_FIELDS = new String[]{
|
||||
"name",
|
||||
"tld",
|
||||
"cca2",
|
||||
"ccn3",
|
||||
"cca3",
|
||||
"cioc",
|
||||
"independent",
|
||||
"status",
|
||||
"unMember",
|
||||
"currencies",
|
||||
"idd",
|
||||
"region",
|
||||
"subregion",
|
||||
"languages",
|
||||
"translations",
|
||||
"landlocked",
|
||||
"borders",
|
||||
"area",
|
||||
"flags",
|
||||
"demonyms",
|
||||
"population",
|
||||
"flag",
|
||||
"maps",
|
||||
"gini",
|
||||
"fifa",
|
||||
"car",
|
||||
"timezones",
|
||||
"continents",
|
||||
"coatOfArms",
|
||||
"startOfWeek",
|
||||
"capitalInfo",
|
||||
"postalCode",
|
||||
"capital",
|
||||
"altSpellings",
|
||||
"geolocation",
|
||||
"religion",
|
||||
"ethnicity",
|
||||
"government",
|
||||
"density",
|
||||
"gdp",
|
||||
"nationalHoliday",
|
||||
"anthem",
|
||||
"regionalBlocs",
|
||||
"callingCodes"
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.restcountries.controller;
|
||||
|
||||
import com.restcountries.service.v4.CountryServiceV4;
|
||||
import io.micronaut.http.HttpResponse;
|
||||
import io.micronaut.http.MediaType;
|
||||
import io.micronaut.http.annotation.Controller;
|
||||
import io.micronaut.http.annotation.Get;
|
||||
import io.micronaut.http.annotation.PathVariable;
|
||||
import io.micronaut.http.annotation.QueryValue;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.restcountries.controller.ControllerHelper.hasInvalidFields;
|
||||
|
||||
@Controller("/v4/")
|
||||
public class CountryControllerV4 extends ControllerV4Helper {
|
||||
|
||||
@Get(uri = "all", produces = MediaType.APPLICATION_JSON)
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getAllCountries(@QueryValue("fields") Optional<String> fields) {
|
||||
if (hasInvalidFields(fields)) {
|
||||
return ControllerHelper.badAllRequest();
|
||||
}
|
||||
var countries = CountryServiceV4.getInstance().getAll();
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
|
||||
@Get("alpha/{alphacode}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByAlpha(@PathVariable("alphacode") String alpha,
|
||||
@QueryValue("fields") Optional<String> fields) {
|
||||
if (alpha.contains("codes")) {
|
||||
alpha = alpha.replace("codes=", "");
|
||||
}
|
||||
if (isEmpty(alpha) || alpha.length() < 2 || alpha.length() > 3) {
|
||||
return ControllerHelper.badRequest();
|
||||
}
|
||||
var country = CountryServiceV4.getInstance().getByAlpha(alpha);
|
||||
if (country != null && !country.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountry(country, fields));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
}
|
||||
|
||||
@Get("alpha/")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByAlphaList(@QueryParam("codes") String codes,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
if (isEmpty(codes) || codes.length() < 2 || (codes.length() > 3 && !codes.contains(","))) {
|
||||
return ControllerHelper.badRequest();
|
||||
}
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByCodeList(codes);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return ControllerHelper.internalError();
|
||||
}
|
||||
}
|
||||
|
||||
@Get("currency/{currency}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByCurrency(@PathVariable("currency") String currency,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
if (isEmpty(currency)) {
|
||||
return ControllerHelper.badRequest();
|
||||
}
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByCurrency(currency);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return ControllerHelper.internalError();
|
||||
}
|
||||
}
|
||||
|
||||
@Get("name/{name}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByName(@PathVariable("name") String name,
|
||||
@QueryParam("fullText") Optional<Boolean> fullText,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByName(name, fullText.orElse(false));
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("capital/{capital}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByCapital(@PathVariable("capital") String capital,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByCapital(capital);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("region/{region}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByContinent(@PathVariable("region") String region,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByRegion(region);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("subregion/{subregion}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getBySubRegion(@PathVariable("subregion") String subregion,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getBySubregion(subregion);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("lang/{lang}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByLanguage(@PathVariable("lang") String language,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByLanguage(language);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("demonym/{demonym}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByDemonym(@PathVariable("demonym") String demonym,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByDemonym(demonym);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("translation/{translation}")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getByTranslation(@PathVariable("translation") String translation,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var countries = CountryServiceV4.getInstance().getByTranslation(translation);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Get("independent")
|
||||
@Schema(name = "RestCountries")
|
||||
public Object getIndependentCountries(@QueryParam("status") Optional<Boolean> status,
|
||||
@QueryParam("fields") Optional<String> fields) {
|
||||
try {
|
||||
var result = true;
|
||||
if (status.isPresent()) {
|
||||
result = Boolean.TRUE.equals(status.get());
|
||||
}
|
||||
var countries = CountryServiceV4.getInstance().getIndependent(result);
|
||||
if (!countries.isEmpty()) {
|
||||
return ControllerHelper.ok(checkFieldsAndParseCountries(fields, countries));
|
||||
}
|
||||
return ControllerHelper.notFound();
|
||||
} catch (Exception e) {
|
||||
return HttpResponse.serverError(Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,39 +6,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class BaseCountry {
|
||||
public class BaseCountry extends BaseCountryCore {
|
||||
|
||||
private Name name;
|
||||
private List<String> tld;
|
||||
private String cca2;
|
||||
private String ccn3;
|
||||
private String cca3;
|
||||
private String cioc;
|
||||
private Boolean independent;
|
||||
private String status;
|
||||
private Boolean unMember;
|
||||
private Map<String, Currency> currencies;
|
||||
private Idd idd;
|
||||
private List<String> capital;
|
||||
private List<String> altSpellings;
|
||||
private String region;
|
||||
private String subregion;
|
||||
private Map<String, String> languages;
|
||||
private Map<String, Map<String, String>> translations;
|
||||
private List<Double> latlng;
|
||||
private Boolean landlocked;
|
||||
private List<String> borders;
|
||||
private Double area;
|
||||
private Map<String, Map<String, String>> demonyms;
|
||||
private List<String> callingCodes;
|
||||
private String flag;
|
||||
private Map<String, String> maps;
|
||||
private Integer population;
|
||||
private Map<String, Double> gini;
|
||||
private String fifa;
|
||||
private Car car;
|
||||
private List<String> timezones;
|
||||
private List<String> continents;
|
||||
|
||||
public Name getName() {
|
||||
return name;
|
||||
@@ -48,62 +24,6 @@ public class BaseCountry {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<String> getTld() {
|
||||
return tld;
|
||||
}
|
||||
|
||||
public void setTld(List<String> tld) {
|
||||
this.tld = tld;
|
||||
}
|
||||
|
||||
public String getCca2() {
|
||||
return cca2;
|
||||
}
|
||||
|
||||
public void setCca2(String cca2) {
|
||||
this.cca2 = cca2;
|
||||
}
|
||||
|
||||
public String getCcn3() {
|
||||
return ccn3;
|
||||
}
|
||||
|
||||
public void setCcn3(String ccn3) {
|
||||
this.ccn3 = ccn3;
|
||||
}
|
||||
|
||||
public String getCioc() {
|
||||
return cioc;
|
||||
}
|
||||
|
||||
public void setCioc(String cioc) {
|
||||
this.cioc = cioc;
|
||||
}
|
||||
|
||||
public Boolean getIndependent() {
|
||||
return independent;
|
||||
}
|
||||
|
||||
public void setIndependent(Boolean independent) {
|
||||
this.independent = independent;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Boolean getUnMember() {
|
||||
return unMember;
|
||||
}
|
||||
|
||||
public void setUnMember(Boolean unMember) {
|
||||
this.unMember = unMember;
|
||||
}
|
||||
|
||||
public Map<String, Currency> getCurrencies() {
|
||||
return currencies;
|
||||
}
|
||||
@@ -113,46 +33,6 @@ public class BaseCountry {
|
||||
this.currencies = currencies;
|
||||
}
|
||||
|
||||
public Idd getIdd() {
|
||||
return idd;
|
||||
}
|
||||
|
||||
public void setIdd(Idd idd) {
|
||||
this.idd = idd;
|
||||
}
|
||||
|
||||
public List<String> getCapital() {
|
||||
return capital;
|
||||
}
|
||||
|
||||
public void setCapital(List<String> capital) {
|
||||
this.capital = capital;
|
||||
}
|
||||
|
||||
public List<String> getAltSpellings() {
|
||||
return altSpellings;
|
||||
}
|
||||
|
||||
public void setAltSpellings(List<String> altSpellings) {
|
||||
this.altSpellings = altSpellings;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getSubregion() {
|
||||
return subregion;
|
||||
}
|
||||
|
||||
public void setSubregion(String subregion) {
|
||||
this.subregion = subregion;
|
||||
}
|
||||
|
||||
public Map<String, String> getLanguages() {
|
||||
return languages;
|
||||
}
|
||||
@@ -169,30 +49,6 @@ public class BaseCountry {
|
||||
this.latlng = latlng;
|
||||
}
|
||||
|
||||
public Boolean getLandlocked() {
|
||||
return landlocked;
|
||||
}
|
||||
|
||||
public void setLandlocked(Boolean landlocked) {
|
||||
this.landlocked = landlocked;
|
||||
}
|
||||
|
||||
public List<String> getBorders() {
|
||||
return borders;
|
||||
}
|
||||
|
||||
public void setBorders(List<String> borders) {
|
||||
this.borders = borders;
|
||||
}
|
||||
|
||||
public Double getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
public void setArea(Double area) {
|
||||
this.area = area;
|
||||
}
|
||||
|
||||
public Map<String, Map<String, String>> getDemonyms() {
|
||||
return demonyms;
|
||||
}
|
||||
@@ -208,36 +64,28 @@ public class BaseCountry {
|
||||
"NativeName=" + name.getNativeName() + "\n" +
|
||||
"Common=" + name.getCommon() + "\n" +
|
||||
"Official=" + name.getOfficial() + "\n" +
|
||||
", tld=" + tld + "\n" +
|
||||
", cca2='" + cca2 + '\'' + "\n" +
|
||||
", ccn3='" + ccn3 + '\'' + "\n" +
|
||||
", cioc='" + cioc + '\'' + "\n" +
|
||||
", independent=" + independent + "\n" +
|
||||
", status='" + status + '\'' + "\n" +
|
||||
", unMember=" + unMember + "\n" +
|
||||
", tld=" + getTld() + "\n" +
|
||||
", cca2='" + getCca2() + '\'' + "\n" +
|
||||
", ccn3='" + getCcn3() + '\'' + "\n" +
|
||||
", cioc='" + getCioc() + '\'' + "\n" +
|
||||
", independent=" + getIndependent() + "\n" +
|
||||
", status='" + getStatus() + '\'' + "\n" +
|
||||
", unMember=" + getUnMember() + "\n" +
|
||||
", currencies=" + currencies + "\n" +
|
||||
", idd=" + idd + "\n" +
|
||||
", capital=" + capital + "\n" +
|
||||
", altSpelling=" + altSpellings + "\n" +
|
||||
", region='" + region + '\'' + "\n" +
|
||||
", subregion='" + subregion + '\'' + "\n" +
|
||||
", idd=" + getIdd() + "\n" +
|
||||
", capital=" + getCapital() + "\n" +
|
||||
", altSpelling=" + getAltSpellings() + "\n" +
|
||||
", region='" + getRegion() + '\'' + "\n" +
|
||||
", subregion='" + getSubregion() + '\'' + "\n" +
|
||||
", language=" + languages + "\n" +
|
||||
", latlng=" + latlng + "\n" +
|
||||
", landlocked=" + landlocked + "\n" +
|
||||
", borders=" + borders + "\n" +
|
||||
", area=" + area + "\n" +
|
||||
", landlocked=" + getLandlocked() + "\n" +
|
||||
", borders=" + getBorders() + "\n" +
|
||||
", area=" + getArea() + "\n" +
|
||||
", demonyms=" + demonyms + "\n" +
|
||||
'}';
|
||||
}
|
||||
|
||||
public String getCca3() {
|
||||
return cca3;
|
||||
}
|
||||
|
||||
public void setCca3(String cca3) {
|
||||
this.cca3 = cca3;
|
||||
}
|
||||
|
||||
public Map<String, Map<String, String>> getTranslations() {
|
||||
return translations;
|
||||
}
|
||||
@@ -246,38 +94,6 @@ public class BaseCountry {
|
||||
this.translations = translations;
|
||||
}
|
||||
|
||||
public List<String> getCallingCodes() {
|
||||
return callingCodes;
|
||||
}
|
||||
|
||||
public void setCallingCodes(List<String> callingCodes) {
|
||||
this.callingCodes = callingCodes;
|
||||
}
|
||||
|
||||
public String getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void setFlag(String flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public Map<String, String> getMaps() {
|
||||
return maps;
|
||||
}
|
||||
|
||||
public void setMaps(Map<String, String> maps) {
|
||||
this.maps = maps;
|
||||
}
|
||||
|
||||
public Integer getPopulation() {
|
||||
return population;
|
||||
}
|
||||
|
||||
public void setPopulation(Integer population) {
|
||||
this.population = population;
|
||||
}
|
||||
|
||||
public Map<String, Double> getGini() {
|
||||
return gini;
|
||||
}
|
||||
@@ -285,36 +101,4 @@ public class BaseCountry {
|
||||
public void setGini(Map<String, Double> gini) {
|
||||
this.gini = gini;
|
||||
}
|
||||
|
||||
public String getFifa() {
|
||||
return fifa;
|
||||
}
|
||||
|
||||
public void setFifa(String fifa) {
|
||||
this.fifa = fifa;
|
||||
}
|
||||
|
||||
public Car getCar() {
|
||||
return car;
|
||||
}
|
||||
|
||||
public void setCar(Car car) {
|
||||
this.car = car;
|
||||
}
|
||||
|
||||
public List<String> getTimezones() {
|
||||
return timezones;
|
||||
}
|
||||
|
||||
public void setTimezones(List<String> timezones) {
|
||||
this.timezones = timezones;
|
||||
}
|
||||
|
||||
public List<String> getContinents() {
|
||||
return continents;
|
||||
}
|
||||
|
||||
public void setContinents(List<String> continents) {
|
||||
this.continents = continents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package com.restcountries.domain.base;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public abstract class BaseCountryCore {
|
||||
|
||||
private List<String> tld;
|
||||
private String cca2;
|
||||
private String ccn3;
|
||||
private String cca3;
|
||||
private String cioc;
|
||||
private Boolean independent;
|
||||
private String status;
|
||||
private Boolean unMember;
|
||||
private Idd idd;
|
||||
private List<String> capital;
|
||||
private List<String> altSpellings;
|
||||
private String region;
|
||||
private String subregion;
|
||||
private Boolean landlocked;
|
||||
private List<String> borders;
|
||||
private Double area;
|
||||
private List<String> callingCodes;
|
||||
private String flag;
|
||||
private Map<String, String> maps;
|
||||
private Integer population;
|
||||
private String fifa;
|
||||
private Car car;
|
||||
private List<String> timezones;
|
||||
private List<String> continents;
|
||||
|
||||
public List<String> getTld() {
|
||||
return tld;
|
||||
}
|
||||
|
||||
public void setTld(List<String> tld) {
|
||||
this.tld = tld;
|
||||
}
|
||||
|
||||
public String getCca2() {
|
||||
return cca2;
|
||||
}
|
||||
|
||||
public void setCca2(String cca2) {
|
||||
this.cca2 = cca2;
|
||||
}
|
||||
|
||||
public String getCcn3() {
|
||||
return ccn3;
|
||||
}
|
||||
|
||||
public void setCcn3(String ccn3) {
|
||||
this.ccn3 = ccn3;
|
||||
}
|
||||
|
||||
public String getCca3() {
|
||||
return cca3;
|
||||
}
|
||||
|
||||
public void setCca3(String cca3) {
|
||||
this.cca3 = cca3;
|
||||
}
|
||||
|
||||
public String getCioc() {
|
||||
return cioc;
|
||||
}
|
||||
|
||||
public void setCioc(String cioc) {
|
||||
this.cioc = cioc;
|
||||
}
|
||||
|
||||
public Boolean getIndependent() {
|
||||
return independent;
|
||||
}
|
||||
|
||||
public void setIndependent(Boolean independent) {
|
||||
this.independent = independent;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Boolean getUnMember() {
|
||||
return unMember;
|
||||
}
|
||||
|
||||
public void setUnMember(Boolean unMember) {
|
||||
this.unMember = unMember;
|
||||
}
|
||||
|
||||
public Idd getIdd() {
|
||||
return idd;
|
||||
}
|
||||
|
||||
public void setIdd(Idd idd) {
|
||||
this.idd = idd;
|
||||
}
|
||||
|
||||
public List<String> getCapital() {
|
||||
return capital;
|
||||
}
|
||||
|
||||
public void setCapital(List<String> capital) {
|
||||
this.capital = capital;
|
||||
}
|
||||
|
||||
public List<String> getAltSpellings() {
|
||||
return altSpellings;
|
||||
}
|
||||
|
||||
public void setAltSpellings(List<String> altSpellings) {
|
||||
this.altSpellings = altSpellings;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getSubregion() {
|
||||
return subregion;
|
||||
}
|
||||
|
||||
public void setSubregion(String subregion) {
|
||||
this.subregion = subregion;
|
||||
}
|
||||
|
||||
public Boolean getLandlocked() {
|
||||
return landlocked;
|
||||
}
|
||||
|
||||
public void setLandlocked(Boolean landlocked) {
|
||||
this.landlocked = landlocked;
|
||||
}
|
||||
|
||||
public List<String> getBorders() {
|
||||
return borders;
|
||||
}
|
||||
|
||||
public void setBorders(List<String> borders) {
|
||||
this.borders = borders;
|
||||
}
|
||||
|
||||
public Double getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
public void setArea(Double area) {
|
||||
this.area = area;
|
||||
}
|
||||
|
||||
public List<String> getCallingCodes() {
|
||||
return callingCodes;
|
||||
}
|
||||
|
||||
public void setCallingCodes(List<String> callingCodes) {
|
||||
this.callingCodes = callingCodes;
|
||||
}
|
||||
|
||||
public String getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void setFlag(String flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public Map<String, String> getMaps() {
|
||||
return maps;
|
||||
}
|
||||
|
||||
public void setMaps(Map<String, String> maps) {
|
||||
this.maps = maps;
|
||||
}
|
||||
|
||||
public Integer getPopulation() {
|
||||
return population;
|
||||
}
|
||||
|
||||
public void setPopulation(Integer population) {
|
||||
this.population = population;
|
||||
}
|
||||
|
||||
public String getFifa() {
|
||||
return fifa;
|
||||
}
|
||||
|
||||
public void setFifa(String fifa) {
|
||||
this.fifa = fifa;
|
||||
}
|
||||
|
||||
public Car getCar() {
|
||||
return car;
|
||||
}
|
||||
|
||||
public void setCar(Car car) {
|
||||
this.car = car;
|
||||
}
|
||||
|
||||
public List<String> getTimezones() {
|
||||
return timezones;
|
||||
}
|
||||
|
||||
public void setTimezones(List<String> timezones) {
|
||||
this.timezones = timezones;
|
||||
}
|
||||
|
||||
public List<String> getContinents() {
|
||||
return continents;
|
||||
}
|
||||
|
||||
public void setContinents(List<String> continents) {
|
||||
this.continents = continents;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import com.restcountries.domain.base.BaseCountryCore;
|
||||
import com.restcountries.domain.v3.v31.CapitalInformation;
|
||||
import com.restcountries.domain.v3.v31.Flag;
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Country extends BaseCountryCore {
|
||||
|
||||
private Name name;
|
||||
private List<Currency> currencies;
|
||||
private List<Language> languages;
|
||||
private List<Translation> translations;
|
||||
private List<Demonym> demonyms;
|
||||
private List<Gini> gini;
|
||||
private Flag flags;
|
||||
private Flag coatOfArms;
|
||||
private String startOfWeek;
|
||||
private CapitalInformation capitalInfo;
|
||||
private Map<String, String> postalCode;
|
||||
private Geolocation geolocation;
|
||||
private List<Religion> religion;
|
||||
private List<Ethnicity> ethnicity;
|
||||
private Government government;
|
||||
private Double density;
|
||||
private GDP gdp;
|
||||
private String nationalHoliday;
|
||||
private String anthem;
|
||||
private List<RegionalBloc> regionalBlocs;
|
||||
private Double hdi;
|
||||
|
||||
public Name getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(Name name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Currency> getCurrencies() {
|
||||
return currencies;
|
||||
}
|
||||
|
||||
public void setCurrencies(List<Currency> currencies) {
|
||||
this.currencies = currencies;
|
||||
}
|
||||
|
||||
public List<Language> getLanguages() {
|
||||
return languages;
|
||||
}
|
||||
|
||||
public void setLanguages(List<Language> languages) {
|
||||
this.languages = languages;
|
||||
}
|
||||
|
||||
public List<Translation> getTranslations() {
|
||||
return translations;
|
||||
}
|
||||
|
||||
public void setTranslations(List<Translation> translations) {
|
||||
this.translations = translations;
|
||||
}
|
||||
|
||||
public List<Demonym> getDemonyms() {
|
||||
return demonyms;
|
||||
}
|
||||
|
||||
public void setDemonyms(List<Demonym> demonyms) {
|
||||
this.demonyms = demonyms;
|
||||
}
|
||||
|
||||
public List<Gini> getGini() {
|
||||
return gini;
|
||||
}
|
||||
|
||||
public void setGini(List<Gini> gini) {
|
||||
this.gini = gini;
|
||||
}
|
||||
|
||||
public Flag getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public void setFlags(Flag flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public Flag getCoatOfArms() {
|
||||
return coatOfArms;
|
||||
}
|
||||
|
||||
public void setCoatOfArms(Flag coatOfArms) {
|
||||
this.coatOfArms = coatOfArms;
|
||||
}
|
||||
|
||||
public String getStartOfWeek() {
|
||||
return startOfWeek;
|
||||
}
|
||||
|
||||
public void setStartOfWeek(String startOfWeek) {
|
||||
this.startOfWeek = startOfWeek;
|
||||
}
|
||||
|
||||
public CapitalInformation getCapitalInfo() {
|
||||
return capitalInfo;
|
||||
}
|
||||
|
||||
public void setCapitalInfo(CapitalInformation capitalInfo) {
|
||||
this.capitalInfo = capitalInfo;
|
||||
}
|
||||
|
||||
public Map<String, String> getPostalCode() {
|
||||
return postalCode;
|
||||
}
|
||||
|
||||
public void setPostalCode(Map<String, String> postalCode) {
|
||||
this.postalCode = postalCode;
|
||||
}
|
||||
|
||||
public Geolocation getGeolocation() {
|
||||
return geolocation;
|
||||
}
|
||||
|
||||
public void setGeolocation(Geolocation geolocation) {
|
||||
this.geolocation = geolocation;
|
||||
}
|
||||
|
||||
public List<Religion> getReligion() {
|
||||
return religion;
|
||||
}
|
||||
|
||||
public void setReligion(List<Religion> religion) {
|
||||
this.religion = religion;
|
||||
}
|
||||
|
||||
public List<Ethnicity> getEthnicity() {
|
||||
return ethnicity;
|
||||
}
|
||||
|
||||
public void setEthnicity(List<Ethnicity> ethnicity) {
|
||||
this.ethnicity = ethnicity;
|
||||
}
|
||||
|
||||
public Government getGovernment() {
|
||||
return government;
|
||||
}
|
||||
|
||||
public void setGovernment(Government government) {
|
||||
this.government = government;
|
||||
}
|
||||
|
||||
public Double getDensity() {
|
||||
return density;
|
||||
}
|
||||
|
||||
public void setDensity(Double density) {
|
||||
this.density = density;
|
||||
}
|
||||
|
||||
public GDP getGdp() {
|
||||
return gdp;
|
||||
}
|
||||
|
||||
public void setGdp(GDP gdp) {
|
||||
this.gdp = gdp;
|
||||
}
|
||||
|
||||
public String getNationalHoliday() {
|
||||
return nationalHoliday;
|
||||
}
|
||||
|
||||
public void setNationalHoliday(String nationalHoliday) {
|
||||
this.nationalHoliday = nationalHoliday;
|
||||
}
|
||||
|
||||
public String getAnthem() {
|
||||
return anthem;
|
||||
}
|
||||
|
||||
public void setAnthem(String anthem) {
|
||||
this.anthem = anthem;
|
||||
}
|
||||
|
||||
public List<RegionalBloc> getRegionalBlocs() {
|
||||
return regionalBlocs;
|
||||
}
|
||||
|
||||
public void setRegionalBlocs(List<RegionalBloc> regionalBlocs) {
|
||||
this.regionalBlocs = regionalBlocs;
|
||||
}
|
||||
|
||||
public Double getHdi() {
|
||||
return hdi;
|
||||
}
|
||||
|
||||
public void setHdi(Double hdi) {
|
||||
this.hdi = hdi;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Currency {
|
||||
private String code;
|
||||
private String name;
|
||||
private String symbol;
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public void setSymbol(String symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Demonym {
|
||||
private String lang;
|
||||
private String male;
|
||||
private String female;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getMale() {
|
||||
return male;
|
||||
}
|
||||
|
||||
public void setMale(String male) {
|
||||
this.male = male;
|
||||
}
|
||||
|
||||
public String getFemale() {
|
||||
return female;
|
||||
}
|
||||
|
||||
public void setFemale(String female) {
|
||||
this.female = female;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Ethnicity {
|
||||
private String name;
|
||||
private Double percentage;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Double getPercentage() {
|
||||
return percentage;
|
||||
}
|
||||
|
||||
public void setPercentage(Double percentage) {
|
||||
this.percentage = percentage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class GDP {
|
||||
private Long total;
|
||||
private Long perCapita;
|
||||
|
||||
public Long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(Long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public Long getPerCapita() {
|
||||
return perCapita;
|
||||
}
|
||||
|
||||
public void setPerCapita(Long perCapita) {
|
||||
this.perCapita = perCapita;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Geolocation {
|
||||
private Double latitude;
|
||||
private Double longitude;
|
||||
|
||||
public Double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(Double latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public Double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public void setLongitude(Double longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Gini {
|
||||
private String year;
|
||||
private Double value;
|
||||
|
||||
public String getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(String year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Government {
|
||||
private String type;
|
||||
private List<Leader> leaders;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public List<Leader> getLeaders() {
|
||||
return leaders;
|
||||
}
|
||||
|
||||
public void setLeaders(List<Leader> leaders) {
|
||||
this.leaders = leaders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Language {
|
||||
private String iso639_1;
|
||||
private String iso639_2;
|
||||
private String name;
|
||||
private String nativeName;
|
||||
|
||||
public String getIso639_1() {
|
||||
return iso639_1;
|
||||
}
|
||||
|
||||
public void setIso639_1(String iso639_1) {
|
||||
this.iso639_1 = iso639_1;
|
||||
}
|
||||
|
||||
public String getIso639_2() {
|
||||
return iso639_2;
|
||||
}
|
||||
|
||||
public void setIso639_2(String iso639_2) {
|
||||
this.iso639_2 = iso639_2;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getNativeName() {
|
||||
return nativeName;
|
||||
}
|
||||
|
||||
public void setNativeName(String nativeName) {
|
||||
this.nativeName = nativeName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Leader {
|
||||
private String title;
|
||||
private String name;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Name {
|
||||
private String common;
|
||||
private String official;
|
||||
private List<NativeName> nativeName;
|
||||
|
||||
public String getCommon() {
|
||||
return common;
|
||||
}
|
||||
|
||||
public void setCommon(String common) {
|
||||
this.common = common;
|
||||
}
|
||||
|
||||
public String getOfficial() {
|
||||
return official;
|
||||
}
|
||||
|
||||
public void setOfficial(String official) {
|
||||
this.official = official;
|
||||
}
|
||||
|
||||
public List<NativeName> getNativeName() {
|
||||
return nativeName;
|
||||
}
|
||||
|
||||
public void setNativeName(List<NativeName> nativeName) {
|
||||
this.nativeName = nativeName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class NativeName {
|
||||
private String lang;
|
||||
private String official;
|
||||
private String common;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getOfficial() {
|
||||
return official;
|
||||
}
|
||||
|
||||
public void setOfficial(String official) {
|
||||
this.official = official;
|
||||
}
|
||||
|
||||
public String getCommon() {
|
||||
return common;
|
||||
}
|
||||
|
||||
public void setCommon(String common) {
|
||||
this.common = common;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class RegionalBloc {
|
||||
private String acronym;
|
||||
private String name;
|
||||
private List<String> otherNames;
|
||||
|
||||
public String getAcronym() {
|
||||
return acronym;
|
||||
}
|
||||
|
||||
public void setAcronym(String acronym) {
|
||||
this.acronym = acronym;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<String> getOtherNames() {
|
||||
if (otherNames == null) {
|
||||
otherNames = new ArrayList<>();
|
||||
}
|
||||
return otherNames;
|
||||
}
|
||||
|
||||
public void setOtherNames(List<String> otherNames) {
|
||||
this.otherNames = otherNames;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Religion {
|
||||
private String name;
|
||||
private Long population;
|
||||
private Double percentage;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getPopulation() {
|
||||
return population;
|
||||
}
|
||||
|
||||
public void setPopulation(Long population) {
|
||||
this.population = population;
|
||||
}
|
||||
|
||||
public Double getPercentage() {
|
||||
return percentage;
|
||||
}
|
||||
|
||||
public void setPercentage(Double percentage) {
|
||||
this.percentage = percentage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.restcountries.domain.v4;
|
||||
|
||||
import io.micronaut.serde.annotation.Serdeable;
|
||||
|
||||
@Serdeable.Serializable
|
||||
public class Translation {
|
||||
private String lang;
|
||||
private String official;
|
||||
private String common;
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getOfficial() {
|
||||
return official;
|
||||
}
|
||||
|
||||
public void setOfficial(String official) {
|
||||
this.official = official;
|
||||
}
|
||||
|
||||
public String getCommon() {
|
||||
return common;
|
||||
}
|
||||
|
||||
public void setCommon(String common) {
|
||||
this.common = common;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package com.restcountries.service.v4;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.restcountries.domain.ICountryRestSymbols;
|
||||
import com.restcountries.domain.v4.Country;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.Normalizer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CountryServiceBaseV4 {
|
||||
|
||||
protected Set<Country> getByAlpha(String alpha, Set<Country> countries) {
|
||||
var result = new HashSet<Country>();
|
||||
for (var country : countries) {
|
||||
if ((country.getCca2() != null && country.getCca2().equalsIgnoreCase(alpha)) ||
|
||||
(country.getCcn3() != null && country.getCcn3().equalsIgnoreCase(alpha)) ||
|
||||
(country.getCca3() != null && country.getCca3().equalsIgnoreCase(alpha)) ||
|
||||
(country.getCioc() != null && country.getCioc().equalsIgnoreCase(alpha))
|
||||
) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByCodeList(String codeList, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
if (codeList == null) {
|
||||
return result;
|
||||
}
|
||||
String[] codes = codeList.split(ICountryRestSymbols.COLON);
|
||||
for (String code : codes) {
|
||||
result.addAll(getByAlpha(code, countries));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByName(String name, boolean fullText, Set<Country> countries) {
|
||||
if (fullText) {
|
||||
return fulltextSearch(name, countries);
|
||||
} else {
|
||||
return substringSearch(name, countries);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Country> fulltextSearch(String name, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (name.equalsIgnoreCase(country.getName().getCommon()) ||
|
||||
name.equalsIgnoreCase(country.getName().getOfficial())) {
|
||||
result.add(country);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<Country> substringSearch(String name, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getName().getCommon().toLowerCase().contains(name.toLowerCase()) ||
|
||||
country.getName().getOfficial().toLowerCase().contains(name.toLowerCase())) {
|
||||
result.add(country);
|
||||
}
|
||||
for (String alternative : country.getAltSpellings()) {
|
||||
if (alternative.toLowerCase().contains(name.toLowerCase())) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByCurrency(String currency, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getCurrencies() != null) {
|
||||
for (var c : country.getCurrencies()) {
|
||||
if ((c.getCode() != null && c.getCode().equalsIgnoreCase(currency)) ||
|
||||
(c.getName() != null && c.getName().toLowerCase().contains(currency.toLowerCase()))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByCapital(String capital, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getCapital() != null) {
|
||||
for (String countryCapital : country.getCapital()) {
|
||||
if (normalize(countryCapital.toLowerCase()).contains(normalize(capital.toLowerCase()))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByRegion(String region, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if ((country.getRegion() != null && country.getRegion().toLowerCase().contains(region.toLowerCase())) ||
|
||||
(country.getSubregion() != null && country.getSubregion().equalsIgnoreCase(region))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getBySubregion(String subregion, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getSubregion() != null &&
|
||||
(country.getSubregion().toLowerCase().contains(subregion.toLowerCase()) ||
|
||||
country.getSubregion().equalsIgnoreCase(subregion))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByLanguage(String language, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getLanguages() != null) {
|
||||
for (var lang : country.getLanguages()) {
|
||||
if ((lang.getName() != null && lang.getName().equalsIgnoreCase(language)) ||
|
||||
(lang.getIso639_1() != null && lang.getIso639_1().equalsIgnoreCase(language)) ||
|
||||
(lang.getIso639_2() != null && lang.getIso639_2().equalsIgnoreCase(language))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByDemonym(String demonym, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getDemonyms() != null) {
|
||||
for (var d : country.getDemonyms()) {
|
||||
if ((d.getMale() != null && d.getMale().toLowerCase().contains(demonym.toLowerCase())) ||
|
||||
(d.getFemale() != null && d.getFemale().toLowerCase().contains(demonym.toLowerCase()))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Set<Country> getByTranslation(String translation, Set<Country> countries) {
|
||||
Set<Country> result = new HashSet<>();
|
||||
for (var country : countries) {
|
||||
if (country.getTranslations() != null) {
|
||||
for (var t : country.getTranslations()) {
|
||||
if ((t.getOfficial() != null && t.getOfficial().toLowerCase().contains(translation.toLowerCase())) ||
|
||||
(t.getCommon() != null && t.getCommon().toLowerCase().contains(translation.toLowerCase()))) {
|
||||
result.add(country);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String normalize(String string) {
|
||||
return Normalizer.normalize(string, Normalizer.Form.NFD)
|
||||
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
|
||||
}
|
||||
|
||||
protected Set<Country> loadJson(String filename) {
|
||||
Set<Country> countries = new HashSet<>();
|
||||
InputStream is = CountryServiceBaseV4.class.getClassLoader().getResourceAsStream(filename);
|
||||
Gson gson = new Gson();
|
||||
try {
|
||||
JsonReader reader = new JsonReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
Country country = gson.fromJson(reader, Country.class);
|
||||
countries.add(country);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return countries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.restcountries.service.v4;
|
||||
|
||||
import com.restcountries.domain.v4.Country;
|
||||
|
||||
import java.text.Normalizer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CountryServiceV4 extends CountryServiceBaseV4 {
|
||||
|
||||
private static Set<Country> countries;
|
||||
|
||||
private CountryServiceV4() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
private static class InstanceHolder {
|
||||
private static final CountryServiceV4 INSTANCE = new CountryServiceV4();
|
||||
}
|
||||
|
||||
public static CountryServiceV4 getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
public Set<Country> getAll() {
|
||||
return countries;
|
||||
}
|
||||
|
||||
public Set<Country> getByAlpha(String alpha) {
|
||||
return super.getByAlpha(alpha, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByName(String name, boolean isFullText) {
|
||||
return super.getByName(name, isFullText, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByCurrency(String currency) {
|
||||
return super.getByCurrency(currency, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByCodeList(String codeList) {
|
||||
return super.getByCodeList(codeList, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByCapital(String capital) {
|
||||
return super.getByCapital(capital, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByRegion(String region) {
|
||||
return super.getByRegion(region, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getBySubregion(String subregion) {
|
||||
return super.getBySubregion(subregion, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByLanguage(String language) {
|
||||
return super.getByLanguage(language, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByDemonym(String demonym) {
|
||||
return super.getByDemonym(demonym, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getByTranslation(String translation) {
|
||||
return super.getByTranslation(translation, countries);
|
||||
}
|
||||
|
||||
public Set<Country> getIndependent(boolean status) {
|
||||
return countries.stream().filter(country -> {
|
||||
var independent = Boolean.TRUE.equals(country.getIndependent());
|
||||
return independent == status;
|
||||
}).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String normalize(String string) {
|
||||
return Normalizer.normalize(string, Normalizer.Form.NFD)
|
||||
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
countries = super.loadJson("countriesV4.json");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,303 +0,0 @@
|
||||
REST Countries 🇵🇪
|
||||
=======
|
||||
|
||||
Get information about countries via a RESTful API
|
||||
|
||||
*Current version: 3.1*
|
||||
|
||||
# About this Project
|
||||
|
||||
This project is inspired on restcountries.eu by Fayder Florez. Although the original project has now
|
||||
moved to
|
||||
a subscription base API, this project is still Open Source and Free to use.
|
||||
|
||||
## Important Information
|
||||
|
||||
* The structure of V2 has been reverted to its original form from the [Original Project] to maintain
|
||||
compatibility.
|
||||
* ***Only the latest version will receive updates and improvements.***
|
||||
|
||||
# REST Countries
|
||||
|
||||
You can access API through https://restcountries.com/v3.1/all but in order to get a faster response,
|
||||
you should filter the results by the fields you need.
|
||||
Like
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/all?fields=name,flags`
|
||||
```
|
||||
|
||||
# Contributing
|
||||
|
||||
Any help is always welcome! Just edit the relevant file and create a new Merge Request or you can
|
||||
also
|
||||
donate using [Patreon](https://www.patreon.com/amatos)
|
||||
or [PayPal](https://www.paypal.me/amatosg/15).
|
||||
|
||||
# Donations
|
||||
|
||||
This are getting out of control (in a positive way).
|
||||
I'm getting about 4 million hits **each day** and that means CPU ussage (sometimes at 99%) and also
|
||||
bandwidth consumption (120 GB **per day!**) so costs have obviously increased. **Please**, consider
|
||||
making a donation on [Patreon](https://www.patreon.com/amatos)
|
||||
or [PayPal](https://www.paypal.me/amatosg/15). This will help me pay the server's bills
|
||||
|
||||
# Fields (mandatory)
|
||||
|
||||
You can check the [FIELDS.md](https://gitlab.com/restcountries/restcountries/-/blob/master/FIELDS.md) file to get a description for each field (thanks to
|
||||
@ePascalC!). You **must** specify the fields you need (up to 10 fields) when calling the `all` endpoints.
|
||||
|
||||
# API Endpoints
|
||||
|
||||
## Using this Project
|
||||
|
||||
- [Famosos](https://famosos.com)
|
||||
- [Cultural Care](https://www.culturalcare.world/)
|
||||
- [Covidata](https://worldcovidata.com/)
|
||||
- [Asendia](https://tracking.asendia.com)
|
||||
- [Picker](https://mwb.pickerexpress.com/#/login)
|
||||
|
||||
# Endpoints
|
||||
|
||||
Below are described the REST endpoints available that you can use to search for countries
|
||||
|
||||
## Latest added Enpoint
|
||||
|
||||
### Independent
|
||||
|
||||
Now you can get all independent (or not independent) countries by calling this endpoint:
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/independent?status=true
|
||||
```
|
||||
|
||||
If you don't specify the status, true will be taken as default. You can mix it with the `fields`
|
||||
filter like this:
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/independent?status=true&fields=languages,capital
|
||||
```
|
||||
|
||||
## All
|
||||
You **must** specify the fields you need (up to 10 fields) when calling the `all` endpoints,
|
||||
otherwise you'll get a `bad request` response. Please see [this issue](https://gitlab.com/restcountries/restcountries/-/issues/265)
|
||||
for more information. This applies to all versions.
|
||||
``` html
|
||||
https://restcountries.com/v3.1/all
|
||||
```
|
||||
|
||||
## Name
|
||||
|
||||
**Search** by country name. If you want to get an exact match, use the next endpoint. It can be the
|
||||
common or official value
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/name/{name}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/name/eesti
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/name/deutschland
|
||||
```
|
||||
|
||||
## Full Name
|
||||
|
||||
Search by country's full name. It can be the common or official value
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/name/{name}?fullText=true
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/name/aruba?fullText=true
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
Search by cca2, ccn3, cca3 or cioc country code (yes, any!)
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/alpha/{code}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/alpha/co
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/alpha/col
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/alpha/170
|
||||
```
|
||||
|
||||
## List of codes
|
||||
|
||||
Search by cca2, ccn3, cca3 or cioc country code (yes, any!)
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/alpha?codes={code},{code},{code}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/alpha?codes=170,no,est,pe
|
||||
```
|
||||
|
||||
## Currency
|
||||
|
||||
Search by currency code or name
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/currency/{currency}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/currency/cop
|
||||
```
|
||||
|
||||
## Demonym
|
||||
|
||||
Now you can search by how a citizen is called.
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/demonym/{demonym}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/demonym/peruvian
|
||||
```
|
||||
|
||||
## Language
|
||||
|
||||
Search by language code or name
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/lang/{language}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/lang/cop
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/lang/spanish
|
||||
```
|
||||
|
||||
## Capital city
|
||||
|
||||
Search by capital city
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/capital/{capital}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/capital/tallinn
|
||||
```
|
||||
|
||||
## Calling code
|
||||
|
||||
In version 3, calling codes are in the _idd_ object. There is no implementation
|
||||
to search by calling codes in V3.
|
||||
|
||||
## Region
|
||||
|
||||
Search by region (replace X with the version you want to use)
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/region/{region}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/region/europe
|
||||
```
|
||||
|
||||
## Subregions
|
||||
|
||||
You can search by subregions (replace X with the version you want to use)
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/subregion/{subregion}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/subregion/Northern Europe
|
||||
```
|
||||
|
||||
## Translation
|
||||
|
||||
You can search by any translation name
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/translation/{translation}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/translation/germany
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/translation/alemania
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/translation/Saksamaa
|
||||
```
|
||||
|
||||
## Filter Response
|
||||
|
||||
You can filter the output of your request to include only the specified fields.
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/{service}?fields={field},{field},{field}
|
||||
```
|
||||
|
||||
``` html
|
||||
https://restcountries.com/v3.1/all?fields=name,capital,currencies
|
||||
```
|
||||
|
||||
## REST Countries Typed API Package
|
||||
Yusif Aliyev from Azerbaijan created [an npm package](https://www.npmjs.com/package/@yusifaliyevpro/countries)
|
||||
which provides TypeScript support for the REST Countries API. Everyone can use
|
||||
the package for their own purpose.
|
||||
This package offers full type and autocomplete support for anyone using
|
||||
JavaScript or TypeScript. Users no longer need to spend time reading
|
||||
documentation or manually writing API URLs and types. You can easily use
|
||||
all the package's functionalities by calling its functions.
|
||||
He is also open to contributing further improvements.
|
||||
|
||||
You can find the code [here](https://github.com/yusifaliyevpro/countries)
|
||||
|
||||
## Similar projects
|
||||
|
||||
* [REST Countries] (original project)
|
||||
* [Countries of the world]
|
||||
* [REST Countries Node.js]
|
||||
* [REST Countries Ruby]
|
||||
* [REST Countries Go]
|
||||
* [REST Countries Python]
|
||||
* [world-currencies]
|
||||
|
||||
[world-currencies]: https://github.com/wiredmax/world-currencies
|
||||
|
||||
[REST Countries Node.js]: https://github.com/aredo/restcountries
|
||||
|
||||
[REST Countries Ruby]: https://github.com/davidesantangelo/restcountry
|
||||
|
||||
[REST Countries Go]: https://github.com/alediaferia/gocountries
|
||||
|
||||
[REST Countries Python]: https://github.com/SteinRobert/python-restcountries
|
||||
|
||||
[Countries of the world]: http://countries.petethompson.net
|
||||
|
||||
[REST Countries]: https://github.com/apilayer/restcountries
|
||||
|
||||
[Original Project]: https://github.com/apilayer/restcountries/
|
||||
|
||||
[donation]: https://www.paypal.me/amatosg/15
|
||||
|
||||
[donate]: https://www.paypal.me/amatosg/15
|
||||
@@ -1,63 +1,615 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>REST Countries</title>
|
||||
|
||||
<!-- Flatdoc -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src='https://cdn.rawgit.com/rstacruz/flatdoc/v0.9.0/legacy.js'></script>
|
||||
<script src='https://cdn.rawgit.com/rstacruz/flatdoc/v0.9.0/flatdoc.js'></script>
|
||||
|
||||
<!-- Flatdoc theme -->
|
||||
<link href='https://cdn.rawgit.com/rstacruz/flatdoc/v0.9.0/theme-white/style.css' rel='stylesheet'>
|
||||
<script src='https://cdn.rawgit.com/rstacruz/flatdoc/v0.9.0/theme-white/script.js'></script>
|
||||
|
||||
<!-- Meta -->
|
||||
<meta content="REST Countries" property="og:title">
|
||||
<meta content="Get information about countries via a RESTful API" name="description">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>REST Countries - Get information about countries via a RESTful API</title>
|
||||
<meta name="description"
|
||||
content="Get information about countries via a RESTful API. Access information about 250+ countries including flags, languages, currencies, and more.">
|
||||
<meta name="keywords" content="rest,api,countries,world,json">
|
||||
<meta name="author" content="Fayder Florez">
|
||||
<link rel="shortcut icon" href="img/favicon.ico"/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Libre+Baskerville:wght@400;700&display=swap"
|
||||
rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #fafaf8;
|
||||
--text: #1a1a1a;
|
||||
--accent: #2563eb;
|
||||
--accent-dark: #1e40af;
|
||||
--warning: #d97706;
|
||||
--border: #e0e0e0;
|
||||
--subtle: #666;
|
||||
--card-bg: #fff;
|
||||
}
|
||||
|
||||
<!-- Custom -->
|
||||
<link rel="shortcut icon" href="img/favicon.ico" />
|
||||
<script src="https://checkout.stripe.com/checkout.js"></script>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
<!-- Initializer -->
|
||||
<script>
|
||||
Flatdoc.run({
|
||||
fetcher: Flatdoc.file('flatdoc.md')
|
||||
});
|
||||
</script>
|
||||
|
||||
<style type="text/css" media="screen">
|
||||
body {
|
||||
font-family: Verdana, sans-serif;
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.7;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
/* Announcement Banner */
|
||||
.announcement-banner {
|
||||
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||||
border-bottom: 2px solid var(--warning);
|
||||
padding: 1.5rem 0;
|
||||
animation: slideDown 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.announcement-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.announcement-badge {
|
||||
background: var(--warning);
|
||||
color: white;
|
||||
padding: 0.35rem 0.8rem;
|
||||
font-size: 0.7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.announcement-text {
|
||||
flex: 1;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.announcement-text strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.header {
|
||||
padding: 4rem 0 3rem;
|
||||
animation: fadeIn 0.8s ease-out 0.2s backwards;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: 'Libre Baskerville', serif;
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-size: 1.25rem;
|
||||
color: var(--subtle);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
gap: 3rem;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.stat {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-family: 'Libre Baskerville', serif;
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
display: block;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.875rem;
|
||||
color: var(--subtle);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
.section {
|
||||
padding: 4rem 0;
|
||||
animation: fadeIn 1s ease-out 0.4s backwards;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--subtle);
|
||||
margin-bottom: 2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border);
|
||||
padding: 1.5rem;
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
font-size: 0.9rem;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.code-block code {
|
||||
color: var(--text);
|
||||
display: block;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.code-comment {
|
||||
color: var(--subtle);
|
||||
}
|
||||
|
||||
/* Documentation Cards */
|
||||
.doc-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.doc-card {
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border);
|
||||
padding: 1.5rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.doc-card:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.doc-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.doc-description {
|
||||
font-size: 0.9rem;
|
||||
color: var(--subtle);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
background: #f3f4f6;
|
||||
padding: 0.4rem 0.6rem;
|
||||
font-size: 0.85rem;
|
||||
display: inline-block;
|
||||
margin-top: 0.75rem;
|
||||
color: var(--accent-dark);
|
||||
}
|
||||
|
||||
.endpoint-example {
|
||||
font-size: 0.8rem;
|
||||
color: var(--subtle);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Info box */
|
||||
.info-box {
|
||||
background: #eff6ff;
|
||||
border-left: 3px solid var(--accent);
|
||||
padding: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.info-box a {
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Similar projects */
|
||||
.similar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.similar-grid a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
padding: 0.5rem 0;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.similar-grid a:hover {
|
||||
color: var(--accent-dark);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
padding: 3rem 0;
|
||||
border-top: 1px solid var(--border);
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.footer-title {
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.footer-links li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: var(--subtle);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
margin-top: 3rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid var(--border);
|
||||
text-align: center;
|
||||
color: var(--subtle);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.logo {
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
|
||||
.stats {
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.stat {
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.announcement-content {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body role='flatdoc'>
|
||||
|
||||
<div class='header'>
|
||||
<div class='left'>
|
||||
<h1>REST Countries</h1>
|
||||
<ul>
|
||||
<li><a href='https://gitlab.com/amatos/rest-countries'>View on GitLab</a></li>
|
||||
<li><a href='https://gitlab.com/amatos/rest-countries/-/issues'>Issues</a></li>
|
||||
</ul>
|
||||
<body>
|
||||
<!-- Announcement Banner -->
|
||||
<div class="announcement-banner">
|
||||
<div class="container">
|
||||
<div class="announcement-content">
|
||||
<span class="announcement-badge">v4 Preview</span>
|
||||
<div class="announcement-text">
|
||||
<strong>RestCountries v4 has been released.</strong> This version is currently in preview and should not
|
||||
be used in production yet. Please report any issues or feature requests through the <a
|
||||
href="https://gitlab.com/restcountries/restcountries/-/issues"
|
||||
style="color: var(--accent); text-decoration: underline;">GitLab issues board</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='content-root'>
|
||||
<div class='menubar'>
|
||||
<div class='menu section' role='flatdoc-menu'></div>
|
||||
</div>
|
||||
<div role='flatdoc-content' class='content'></div>
|
||||
</div>
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<h1 class="logo">REST Countries</h1>
|
||||
<p class="tagline">Get information about countries via a RESTful API</p>
|
||||
<p style="color: var(--subtle); font-size: 0.9rem;">Current version: v3.1 — v4 in preview</p>
|
||||
|
||||
<script src="js/restc.min.js" type="text/javascript" charset="utf-8" async defer></script>
|
||||
<div class="stats">
|
||||
<div class="stat">
|
||||
<span class="stat-number">4M+</span>
|
||||
<span class="stat-label">Daily Requests</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-number">250+</span>
|
||||
<span class="stat-label">Countries</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-number">Open Source</span>
|
||||
<span class="stat-label">Free to Use</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Quick Start -->
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Quick Start</h2>
|
||||
|
||||
<div class="info-box">
|
||||
<strong>Fields filter:</strong> You <strong>must</strong> specify the fields you need (up to 10 fields) when
|
||||
calling the <code>all</code> endpoint, otherwise you'll get a <code>bad request</code> response. See <a
|
||||
href="https://gitlab.com/restcountries/restcountries/-/issues/265">this issue</a> for more information.
|
||||
</div>
|
||||
|
||||
<div class="code-block">
|
||||
<code><span class="code-comment"># Get all countries (filtered by fields)</span>
|
||||
https://restcountries.com/v3.1/all?fields=name,capital,currencies
|
||||
|
||||
<span class="code-comment"># Get country by name</span>
|
||||
https://restcountries.com/v3.1/name/peru
|
||||
|
||||
<span class="code-comment"># Get country by code</span>
|
||||
https://restcountries.com/v3.1/alpha/co
|
||||
|
||||
<span class="code-comment"># Filter response fields</span>
|
||||
https://restcountries.com/v3.1/{service}?fields={field},{field},{field}</code>
|
||||
</div>
|
||||
|
||||
<p style="margin-top: 1rem; font-size: 0.9rem; color: var(--subtle);">
|
||||
Check the <a href="https://gitlab.com/restcountries/restcountries/-/blob/master/FIELDS.md"
|
||||
style="color: var(--accent);">FIELDS.md</a> file for a description of each field.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- API Endpoints -->
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">API Endpoints</h2>
|
||||
|
||||
<div class="doc-grid">
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">All Countries</div>
|
||||
<div class="doc-description">Retrieve information about all countries. Must specify fields.</div>
|
||||
<code class="endpoint">/v3.1/all?fields=name,flags</code>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Name</div>
|
||||
<div class="doc-description">Search by country name (common or official value)</div>
|
||||
<code class="endpoint">/v3.1/name/{name}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/name/eesti</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">Full Name</div>
|
||||
<div class="doc-description">Search by country's full name (common or official)</div>
|
||||
<code class="endpoint">/v3.1/name/{name}?fullText=true</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/name/aruba?fullText=true</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Code</div>
|
||||
<div class="doc-description">Search by cca2, ccn3, cca3 or cioc country code</div>
|
||||
<code class="endpoint">/v3.1/alpha/{code}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/alpha/co, /v3.1/alpha/col, /v3.1/alpha/170</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">List of Codes</div>
|
||||
<div class="doc-description">Search by multiple country codes at once</div>
|
||||
<code class="endpoint">/v3.1/alpha?codes={code},{code}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/alpha?codes=170,no,est,pe</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Currency</div>
|
||||
<div class="doc-description">Search by currency code or name</div>
|
||||
<code class="endpoint">/v3.1/currency/{currency}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/currency/cop</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Language</div>
|
||||
<div class="doc-description">Search by language code or name</div>
|
||||
<code class="endpoint">/v3.1/lang/{language}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/lang/spanish</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Capital City</div>
|
||||
<div class="doc-description">Search by capital city</div>
|
||||
<code class="endpoint">/v3.1/capital/{capital}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/capital/tallinn</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Region</div>
|
||||
<div class="doc-description">Filter countries by region</div>
|
||||
<code class="endpoint">/v3.1/region/{region}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/region/europe</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Subregion</div>
|
||||
<div class="doc-description">Filter countries by subregion</div>
|
||||
<code class="endpoint">/v3.1/subregion/{subregion}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/subregion/Northern Europe</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Demonym</div>
|
||||
<div class="doc-description">Search by how a citizen is called</div>
|
||||
<code class="endpoint">/v3.1/demonym/{demonym}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/demonym/peruvian</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">By Translation</div>
|
||||
<div class="doc-description">Search by any translation name</div>
|
||||
<code class="endpoint">/v3.1/translation/{translation}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/translation/alemania</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">Independent</div>
|
||||
<div class="doc-description">Get all independent (or non-independent) countries</div>
|
||||
<code class="endpoint">/v3.1/independent?status=true</code>
|
||||
<div class="endpoint-example">Combine with fields: ?status=true&fields=languages,capital</div>
|
||||
</div>
|
||||
|
||||
<div class="doc-card">
|
||||
<div class="doc-title">Filter Response</div>
|
||||
<div class="doc-description">Filter the output to include only specified fields</div>
|
||||
<code class="endpoint">/v3.1/{service}?fields={field},{field}</code>
|
||||
<div class="endpoint-example">e.g. /v3.1/all?fields=name,capital,currencies</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contributing -->
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Contributing & Donations</h2>
|
||||
|
||||
<p style="font-size: 0.95rem; margin-bottom: 1.5rem;">
|
||||
Any help is always welcome! Just edit the relevant file and create a new Merge Request or you can also
|
||||
donate using
|
||||
<a href="https://www.patreon.com/amatos" style="color: var(--accent); text-decoration: none;">Patreon</a> or
|
||||
<a href="https://www.paypal.me/amatosg/15" style="color: var(--accent); text-decoration: none;">PayPal</a>.
|
||||
</p>
|
||||
|
||||
<div class="info-box">
|
||||
Requests are growing fast — about 4 million hits <strong>each day</strong> and 120 GB of bandwidth
|
||||
<strong>per day</strong>. Please consider making a
|
||||
<a href="https://www.patreon.com/amatos">donation</a> to help cover server costs.
|
||||
</div>
|
||||
|
||||
<h2 class="section-title" style="margin-top: 3rem;">Similar Projects</h2>
|
||||
|
||||
<div class="similar-grid">
|
||||
<a href="https://github.com/apilayer/restcountries">REST Countries (original)</a>
|
||||
<a href="http://countries.petethompson.net">Countries of the World</a>
|
||||
<a href="https://github.com/aredo/restcountries">REST Countries Node.js</a>
|
||||
<a href="https://github.com/davidesantangelo/restcountry">REST Countries Ruby</a>
|
||||
<a href="https://github.com/alediaferia/gocountries">REST Countries Go</a>
|
||||
<a href="https://github.com/SteinRobert/python-restcountries">REST Countries Python</a>
|
||||
<a href="https://github.com/wiredmax/world-currencies">world-currencies</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<div class="footer-title">Product</div>
|
||||
<ul class="footer-links">
|
||||
<li><a href="https://gitlab.com/restcountries/restcountries/-/blob/master/FIELDS.md">Fields
|
||||
Documentation</a></li>
|
||||
<li>
|
||||
<a href="https://gitlab.com/restcountries/restcountries/-/blob/master/README.md">Documentation</a>
|
||||
</li>
|
||||
<li><a href="https://gitlab.com/restcountries/restcountries/-/issues">Support</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<div class="footer-title">Resources</div>
|
||||
<ul class="footer-links">
|
||||
<li><a href="https://gitlab.com/restcountries/restcountries">GitLab Repository</a></li>
|
||||
<li><a href="https://gitlab.com/restcountries/restcountries/-/issues">Report Issues</a></li>
|
||||
<li><a href="https://www.npmjs.com/package/@yusifaliyevpro/countries">TypeScript Package</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<div class="footer-title">Support the Project</div>
|
||||
<ul class="footer-links">
|
||||
<li><a href="https://www.patreon.com/amatos">Donate via Patreon</a></li>
|
||||
<li><a href="https://www.paypal.me/amatosg/15">Donate via PayPal</a></li>
|
||||
<li><a href="https://gitlab.com/restcountries/restcountries/contribute">Contribute</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-bottom">
|
||||
<p>REST Countries is an open-source project inspired by restcountries.eu by Fayder Florez.</p>
|
||||
<p style="margin-top: 1rem; font-size: 0.85rem;">
|
||||
<a href="/terms.html" style="color: var(--subtle); text-decoration: none;">Terms and Conditions</a>
|
||||
·
|
||||
<a href="/privacy.html" style="color: var(--subtle); text-decoration: none;">Privacy Policy</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Privacy Policy - RestCountries</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Libre+Baskerville:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #fafaf8;
|
||||
--text: #1a1a1a;
|
||||
--accent: #2563eb;
|
||||
--border: #e0e0e0;
|
||||
--subtle: #666;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 3rem 2rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: 'Libre Baskerville', serif;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.logo a {
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Libre Baskerville', serif;
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.last-updated {
|
||||
color: var(--subtle);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.25rem;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: #f0fdf4;
|
||||
border-left: 3px solid #16a34a;
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="logo"><a href="/">RestCountries</a></div>
|
||||
</div>
|
||||
|
||||
<h1>Privacy Policy</h1>
|
||||
<p class="last-updated">Last updated: February 3, 2026</p>
|
||||
|
||||
<p>RestCountries respects your privacy. This policy explains how we collect, use, and protect your information.</p>
|
||||
|
||||
<h2>1. Information We Collect</h2>
|
||||
|
||||
<p>As of right now, there is no information that we collect other than the logs from the web server and they are removed every 15 minutes</p>
|
||||
|
||||
<h2>2. Children's Privacy</h2>
|
||||
<p>Our service is not intended for users under 13 years of age. We do not knowingly collect information from children.</p>
|
||||
|
||||
<h2>3. International Users</h2>
|
||||
<p>By using our service, you consent to the processing and storage of your data as described in this policy.</p>
|
||||
|
||||
<h2>4. Changes to This Policy</h2>
|
||||
<p>We may update this privacy policy from time to time.</p>
|
||||
|
||||
<h2>5. Open Source</h2>
|
||||
<p>RestCountries is an open-source project. Our code is publicly available on <a href="https://gitlab.com/restcountries/restcountries">GitLab</a>, allowing you to verify our security and privacy practices.</p>
|
||||
|
||||
<h2>6. Contact</h2>
|
||||
<p>For privacy-related questions or concerns, please contact us through our <a href="https://gitlab.com/restcountries/restcountries/-/issues">GitLab repository</a>.</p>
|
||||
|
||||
<p style="margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--border); color: var(--subtle);">
|
||||
<a href="/">← Back to Home</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,151 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Terms of Service - RestCountries</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Libre+Baskerville:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #fafaf8;
|
||||
--text: #1a1a1a;
|
||||
--accent: #2563eb;
|
||||
--border: #e0e0e0;
|
||||
--subtle: #666;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.8;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 3rem 2rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: 'Libre Baskerville', serif;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.logo a {
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Libre Baskerville', serif;
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.last-updated {
|
||||
color: var(--subtle);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.25rem;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="logo"><a href="/">RestCountries</a></div>
|
||||
</div>
|
||||
|
||||
<h1>Terms of Service</h1>
|
||||
<p class="last-updated">Last updated: 18/02/2026</p>
|
||||
|
||||
<p>By accessing and using the RestCountries API, you agree to be bound by these Terms of Service.</p>
|
||||
|
||||
<h2>1. Acceptance of Terms</h2>
|
||||
<p>By accessing and using the RestCountries API, you accept these terms in full. If you disagree with any part of these terms, you must not use our services.</p>
|
||||
|
||||
<h2>2. API Usage</h2>
|
||||
<p>When using the RestCountries API, you agree to:</p>
|
||||
<ul>
|
||||
<li>Comply with all applicable laws and regulations</li>
|
||||
</ul>
|
||||
|
||||
<h2>3. Prohibited Uses</h2>
|
||||
<p>You may not use the API to:</p>
|
||||
<ul>
|
||||
<li>Violate any laws or regulations</li>
|
||||
<li>Infringe on intellectual property rights</li>
|
||||
<li>Distribute malware or harmful code</li>
|
||||
<li>Scrape or harvest data for resale</li>
|
||||
<li>Impersonate RestCountries or misrepresent your relationship with us</li>
|
||||
</ul>
|
||||
|
||||
<h2>4. Changes to Terms</h2>
|
||||
<p>We reserve the right to modify these terms at any time. Continued use of the API after changes constitutes acceptance of the new terms.</p>
|
||||
|
||||
<h2>5. Limitation of Liability</h2>
|
||||
<p>RestCountries and its operators shall not be liable for any indirect, incidental, special, consequential, or punitive damages resulting from your use of the API.</p>
|
||||
|
||||
<h2>6. Contact</h2>
|
||||
<p>For questions about these terms, please contact us through our <a href="https://gitlab.com/restcountries/restcountries/-/issues">GitLab repository</a>.</p>
|
||||
|
||||
<p style="margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--border); color: var(--subtle);">
|
||||
<a href="/">← Back to Home</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.restcountries;
|
||||
|
||||
import com.restcountries.service.v4.CountryServiceV4;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class RestCountriesV4Test {
|
||||
|
||||
@Test
|
||||
void getAll() {
|
||||
var countries = CountryServiceV4.getInstance().getAll();
|
||||
assertFalse(countries.isEmpty());
|
||||
Assertions.assertEquals(250, countries.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByAlpha() {
|
||||
var countries = CountryServiceV4.getInstance().getByAlpha("CO");
|
||||
assertFalse(countries.isEmpty());
|
||||
Assertions.assertEquals("Colombia",
|
||||
countries.stream().findFirst().map(country -> country.getName().getCommon()).orElseThrow());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByAlphaList() {
|
||||
var countries = CountryServiceV4.getInstance().getByCodeList("de,co");
|
||||
Assertions.assertEquals(2, countries.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCountryByName() {
|
||||
var countries = CountryServiceV4.getInstance().getByName("Peru", false);
|
||||
assertFalse(countries.isEmpty());
|
||||
Assertions.assertEquals("Peru",
|
||||
countries.stream().findFirst().map(country -> country.getName().getCommon()).orElseThrow());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByCodeList() {
|
||||
var countries = CountryServiceV4.getInstance().getByCodeList("PE,NL,DE");
|
||||
Assertions.assertNotNull(countries);
|
||||
assertFalse(countries.isEmpty());
|
||||
Assertions.assertEquals(3, countries.size());
|
||||
var result = countries.stream().allMatch(country ->
|
||||
country.getName().getCommon().contains("Peru") ||
|
||||
country.getName().getCommon().contains("Netherlands") ||
|
||||
country.getName().getCommon().contains("German")
|
||||
);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByCurrency() {
|
||||
var countries = CountryServiceV4.getInstance().getByCurrency("EUR");
|
||||
Assertions.assertNotNull(countries);
|
||||
assertFalse(countries.isEmpty());
|
||||
countries.forEach(country -> {
|
||||
var hasEur = country.getCurrencies().stream()
|
||||
.anyMatch(c -> "EUR".equals(c.getCode()));
|
||||
assertTrue(hasEur);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByCapital() {
|
||||
var countries = CountryServiceV4.getInstance().getByCapital("Helsinki");
|
||||
var result = countries.stream()
|
||||
.anyMatch(country -> country.getName().getCommon().equalsIgnoreCase("Finland"));
|
||||
assertTrue(result);
|
||||
Assertions.assertEquals(1, countries.size());
|
||||
Assertions.assertEquals("Finland",
|
||||
countries.stream().findFirst().map(country -> country.getName().getCommon()).orElseThrow());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByRegion() {
|
||||
var countries = CountryServiceV4.getInstance().getByRegion("Asia");
|
||||
assertFalse(countries.isEmpty());
|
||||
var result = countries.stream()
|
||||
.anyMatch(country -> country.getName().getCommon().equalsIgnoreCase("Bangladesh"));
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBySubregion() {
|
||||
var countries = CountryServiceV4.getInstance().getBySubregion("Middle Africa");
|
||||
assertFalse(countries.isEmpty());
|
||||
var result = countries.stream()
|
||||
.anyMatch(country -> country.getName().getCommon().equalsIgnoreCase("Gabon"));
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByLanguage() {
|
||||
var countries = CountryServiceV4.getInstance().getByLanguage("german");
|
||||
assertFalse(countries.isEmpty());
|
||||
var result = countries.stream()
|
||||
.anyMatch(country -> country.getName().getCommon().equalsIgnoreCase("Liechtenstein"));
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByDemonym() {
|
||||
var countries = CountryServiceV4.getInstance().getByDemonym("chilean");
|
||||
assertFalse(countries.isEmpty());
|
||||
var result = countries.stream()
|
||||
.anyMatch(country -> country.getName().getCommon().equalsIgnoreCase("Chile"));
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getByTranslation() {
|
||||
var countries = CountryServiceV4.getInstance().getByTranslation("Běloruská");
|
||||
assertFalse(countries.isEmpty());
|
||||
Assertions.assertEquals(1, countries.size());
|
||||
Assertions.assertEquals("Belarus", countries.stream().findFirst().get().getName().getCommon());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFlags() {
|
||||
var countries = CountryServiceV4.getInstance().getAll();
|
||||
try {
|
||||
var result = countries.stream().noneMatch(
|
||||
country -> null == country.getFlags().getPng() || null == country.getFlags().getSvg()
|
||||
|| null == country.getFlags().getAlt());
|
||||
assertTrue(result);
|
||||
} catch (Exception ex) {
|
||||
Assertions.fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGeolocation() {
|
||||
var countries = CountryServiceV4.getInstance().getAll();
|
||||
var countriesWithGeo = countries.stream()
|
||||
.filter(c -> c.getGeolocation() != null &&
|
||||
c.getGeolocation().getLatitude() != null &&
|
||||
c.getGeolocation().getLongitude() != null)
|
||||
.count();
|
||||
assertTrue(countriesWithGeo > 200);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCurrenciesAsArray() {
|
||||
var countries = CountryServiceV4.getInstance().getByAlpha("US");
|
||||
assertFalse(countries.isEmpty());
|
||||
var us = countries.stream().findFirst().get();
|
||||
assertFalse(us.getCurrencies().isEmpty());
|
||||
var usd = us.getCurrencies().stream()
|
||||
.filter(c -> "USD".equals(c.getCode()))
|
||||
.findFirst();
|
||||
assertTrue(usd.isPresent());
|
||||
Assertions.assertEquals("United States dollar", usd.get().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLanguagesAsArray() {
|
||||
var countries = CountryServiceV4.getInstance().getByAlpha("CH");
|
||||
assertFalse(countries.isEmpty());
|
||||
var ch = countries.stream().findFirst().get();
|
||||
assertFalse(ch.getLanguages().isEmpty());
|
||||
var hasSwissGerman = ch.getLanguages().stream()
|
||||
.anyMatch(l -> "Swiss German".equals(l.getName()));
|
||||
assertTrue(hasSwissGerman);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNativeNameAsArray() {
|
||||
var countries = CountryServiceV4.getInstance().getByAlpha("BE");
|
||||
assertFalse(countries.isEmpty());
|
||||
var be = countries.stream().findFirst().get();
|
||||
assertFalse(be.getName().getNativeName().isEmpty());
|
||||
var hasFrench = be.getName().getNativeName().stream()
|
||||
.anyMatch(nn -> "fra".equals(nn.getLang()));
|
||||
assertTrue(hasFrench);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIndependent() {
|
||||
var countries = CountryServiceV4.getInstance().getIndependent(true);
|
||||
assertFalse(countries.isEmpty());
|
||||
var nonIndependent = CountryServiceV4.getInstance().getIndependent(false);
|
||||
assertFalse(nonIndependent.isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
package com.restcountries;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class V4JsonStructureTest {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(V4JsonStructureTest.class);
|
||||
private static JsonArray countries;
|
||||
|
||||
@BeforeAll
|
||||
static void loadJson() {
|
||||
var is = V4JsonStructureTest.class.getClassLoader().getResourceAsStream("countriesV4.json");
|
||||
assertNotNull(is, "countriesV4.json not found");
|
||||
countries = JsonParser.parseReader(new InputStreamReader(is, StandardCharsets.UTF_8)).getAsJsonArray();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAllCountriesLoaded() {
|
||||
assertTrue(countries.size() >= 200, "Should have at least 200 countries");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequiredFields() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("name"), "Missing name field");
|
||||
assertTrue(c.has("cca2"), "Missing cca2 field");
|
||||
assertTrue(c.has("cca3"), "Missing cca3 field");
|
||||
assertTrue(c.has("region"), "Missing region field");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNameStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
JsonObject name = c.getAsJsonObject("name");
|
||||
assertNotNull(name, "name should be an object");
|
||||
|
||||
assertTrue(name.has("common") && !name.get("common").isJsonNull(),
|
||||
"name.common should not be null for " + c.get("cca2"));
|
||||
assertTrue(name.has("official") && !name.get("official").isJsonNull(),
|
||||
"name.official should not be null for " + c.get("cca2"));
|
||||
|
||||
String common = name.get("common").getAsString();
|
||||
String official = name.get("official").getAsString();
|
||||
assertFalse(common.isEmpty(), "name.common should not be empty");
|
||||
assertFalse(official.isEmpty(), "name.official should not be empty");
|
||||
|
||||
assertTrue(name.has("nativeName"), "name.nativeName should exist");
|
||||
assertTrue(name.get("nativeName").isJsonArray(),
|
||||
"name.nativeName should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement nn : name.getAsJsonArray("nativeName")) {
|
||||
assertTrue(nn.isJsonObject(), "nativeName entry should be object");
|
||||
JsonObject nnObj = nn.getAsJsonObject();
|
||||
assertTrue(nnObj.has("lang"), "nativeName entry should have lang");
|
||||
assertTrue(nnObj.has("official"), "nativeName entry should have official");
|
||||
assertTrue(nnObj.has("common"), "nativeName entry should have common");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCurrenciesStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("currencies"), "Missing currencies for " + c.get("cca2"));
|
||||
assertTrue(c.get("currencies").isJsonArray(),
|
||||
"currencies should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement curr : c.getAsJsonArray("currencies")) {
|
||||
assertTrue(curr.isJsonObject(), "currency entry should be object");
|
||||
JsonObject currObj = curr.getAsJsonObject();
|
||||
assertTrue(currObj.has("code"), "currency entry should have code");
|
||||
assertTrue(currObj.has("name"), "currency entry should have name");
|
||||
assertTrue(currObj.has("symbol"), "currency entry should have symbol");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLanguagesStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("languages"), "Missing languages for " + c.get("cca2"));
|
||||
assertTrue(c.get("languages").isJsonArray(),
|
||||
"languages should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement lang : c.getAsJsonArray("languages")) {
|
||||
assertTrue(lang.isJsonObject(), "language entry should be object");
|
||||
JsonObject langObj = lang.getAsJsonObject();
|
||||
assertTrue(langObj.has("iso639_1"), "language entry should have iso639_1");
|
||||
assertTrue(langObj.has("iso639_2"), "language entry should have iso639_2");
|
||||
assertTrue(langObj.has("name"), "language entry should have name");
|
||||
assertTrue(langObj.has("nativeName"), "language entry should have nativeName");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGeolocationStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("geolocation"), "Missing geolocation for " + c.get("cca2"));
|
||||
if (!c.get("geolocation").isJsonNull()) {
|
||||
JsonObject geo = c.getAsJsonObject("geolocation");
|
||||
assertTrue(geo.has("latitude"), "geolocation should have latitude");
|
||||
assertTrue(geo.has("longitude"), "geolocation should have longitude");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReligionStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("religion"), "Missing religion for " + c.get("cca2"));
|
||||
assertTrue(c.get("religion").isJsonArray(),
|
||||
"religion should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement r : c.getAsJsonArray("religion")) {
|
||||
assertTrue(r.isJsonObject(), "religion entry should be object");
|
||||
JsonObject rObj = r.getAsJsonObject();
|
||||
assertTrue(rObj.has("name"), "religion entry should have name");
|
||||
assertTrue(rObj.has("population"), "religion entry should have population");
|
||||
assertTrue(rObj.has("percentage"), "religion entry should have percentage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEthnicityStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("ethnicity"), "Missing ethnicity for " + c.get("cca2"));
|
||||
assertTrue(c.get("ethnicity").isJsonArray(),
|
||||
"ethnicity should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement e : c.getAsJsonArray("ethnicity")) {
|
||||
assertTrue(e.isJsonObject(), "ethnicity entry should be object");
|
||||
JsonObject eObj = e.getAsJsonObject();
|
||||
if(!eObj.has("percentage")) {
|
||||
log.error("name: {}", e.toString());
|
||||
}
|
||||
assertTrue(eObj.has("name"), "ethnicity entry should have name");
|
||||
assertTrue(eObj.has("percentage"), "ethnicity entry should have percentage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGovernmentStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("government"), "Missing government for " + c.get("cca2"));
|
||||
if (!c.get("government").isJsonNull()) {
|
||||
JsonObject gov = c.getAsJsonObject("government");
|
||||
assertTrue(gov.has("type"), "government should have type");
|
||||
assertTrue(gov.has("leaders"), "government should have leaders");
|
||||
assertTrue(gov.get("leaders").isJsonArray(), "leaders should be an array");
|
||||
for (JsonElement l : gov.getAsJsonArray("leaders")) {
|
||||
assertTrue(l.isJsonObject(), "leader entry should be an object");
|
||||
JsonObject leader = l.getAsJsonObject();
|
||||
assertTrue(leader.has("title"), "leader should have title");
|
||||
assertTrue(leader.has("name"), "leader should have name");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGdpStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("gdp"), "Missing gdp for " + c.get("cca2"));
|
||||
if (!c.get("gdp").isJsonNull()) {
|
||||
JsonObject gdp = c.getAsJsonObject("gdp");
|
||||
assertTrue(gdp.has("total"), "gdp should have total");
|
||||
assertTrue(gdp.has("perCapita"), "gdp should have perCapita");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGiniStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("gini"), "Missing gini for " + c.get("cca2"));
|
||||
assertTrue(c.get("gini").isJsonArray(),
|
||||
"gini should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement g : c.getAsJsonArray("gini")) {
|
||||
assertTrue(g.isJsonObject(), "gini entry should be object");
|
||||
JsonObject gObj = g.getAsJsonObject();
|
||||
assertTrue(gObj.has("year"), "gini entry should have year");
|
||||
assertTrue(gObj.has("value"), "gini entry should have value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTranslationsStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("translations"), "Missing translations for " + c.get("cca2"));
|
||||
assertTrue(c.get("translations").isJsonArray(),
|
||||
"translations should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement t : c.getAsJsonArray("translations")) {
|
||||
assertTrue(t.isJsonObject(), "translation entry should be object");
|
||||
JsonObject tObj = t.getAsJsonObject();
|
||||
assertTrue(tObj.has("lang"), "translation entry should have lang");
|
||||
assertTrue(tObj.has("official"), "translation entry should have official");
|
||||
assertTrue(tObj.has("common"), "translation entry should have common");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDemonymsStructure() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertTrue(c.has("demonyms"), "Missing demonyms for " + c.get("cca2"));
|
||||
assertTrue(c.get("demonyms").isJsonArray(),
|
||||
"demonyms should be an array for " + c.get("cca2"));
|
||||
|
||||
for (JsonElement d : c.getAsJsonArray("demonyms")) {
|
||||
assertTrue(d.isJsonObject(), "demonym entry should be object");
|
||||
JsonObject dObj = d.getAsJsonObject();
|
||||
assertTrue(dObj.has("lang"), "demonym entry should have lang");
|
||||
assertTrue(dObj.has("male"), "demonym entry should have male");
|
||||
assertTrue(dObj.has("female"), "demonym entry should have female");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testArrayFieldsAreArrays() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
assertIsArrayIfPresent(c, "currencies");
|
||||
assertIsArrayIfPresent(c, "languages");
|
||||
assertIsArrayIfPresent(c, "gini");
|
||||
assertIsArrayIfPresent(c, "translations");
|
||||
assertIsArrayIfPresent(c, "demonyms");
|
||||
assertIsArrayIfPresent(c, "religion");
|
||||
assertIsArrayIfPresent(c, "ethnicity");
|
||||
assertIsArrayIfPresent(c, "regionalBlocs");
|
||||
assertIsArrayIfPresent(c, "callingCodes");
|
||||
assertIsArrayIfPresent(c, "timezones");
|
||||
assertIsArrayIfPresent(c, "borders");
|
||||
assertIsArrayIfPresent(c, "continents");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCca2CodeLength() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
if (c.has("cca2") && !c.get("cca2").isJsonNull()) {
|
||||
String cca2 = c.get("cca2").getAsString();
|
||||
assertEquals(2, cca2.length(), "cca2 should be 2 chars: " + cca2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCca3CodeLength() {
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
if (c.has("cca3") && !c.get("cca3").isJsonNull()) {
|
||||
String cca3 = c.get("cca3").getAsString();
|
||||
assertEquals(3, cca3.length(), "cca3 should be 3 chars: " + cca3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoDuplicateCca2() {
|
||||
Set<String> seen = new HashSet<>();
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
if (c.has("cca2") && !c.get("cca2").isJsonNull()) {
|
||||
String cca2 = c.get("cca2").getAsString();
|
||||
assertTrue(seen.add(cca2), "Duplicate cca2: " + cca2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoDuplicateCca3() {
|
||||
Set<String> seen = new HashSet<>();
|
||||
for (JsonElement el : countries) {
|
||||
JsonObject c = el.getAsJsonObject();
|
||||
if (c.has("cca3") && !c.get("cca3").isJsonNull()) {
|
||||
String cca3 = c.get("cca3").getAsString();
|
||||
assertTrue(seen.add(cca3), "Duplicate cca3: " + cca3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertIsArrayIfPresent(JsonObject obj, String field) {
|
||||
if (obj.has(field) && !obj.get(field).isJsonNull()) {
|
||||
assertTrue(obj.get(field).isJsonArray(),
|
||||
field + " should be an array for " + obj.get("cca2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user