Now I want these GPS position to covert to city name and country name. Problem is that not every GPS coordinate can be translated to city, some of them will be translated rather to a comune (municipality), for example Terenzo44°36'22.2"N 10°04'18.0"E, but in my case I wanted to have saved everything under one name, city name. The other problem is that I want to have only english names like "Cologne" but not "Köln", for example check out this JSON response, notice this part:
You can notice that if type is "street_address" name will be written in german "Kön", but when type is '"locality", "political"'' name will be in english "Cologne". That is why I am gonna always search for a name in a result first where types are "locality", "political".
Here is my code:
using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace ReverseGeocoding
{
class Program
{
static void Main(string[] args)
{
string json = "gpsCoordinates.json";
JsonSerializer serializer = new JsonSerializer();
using (FileStream s = File.Open(json, FileMode.Open))
using (StreamReader sr = new StreamReader(s))
using (JsonReader reader = new JsonTextReader(sr))
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
LatLng latLng = serializer.Deserialize(reader);
if (latLng is not null)
{
Console.WriteLine(
$"Geocode: {latLng.Latitude}, {latLng.Longitude}");
string url =
$@"https://maps.googleapis.com/maps/api/geocode/json?latlng={latLng.Latitude},{latLng.Longitude}&language=en&key=myKey";
string reverseGeocodeJsonResponse;
using (System.Net.WebClient client = new System.Net.WebClient())
{
reverseGeocodeJsonResponse = client.DownloadString(url);
}
JObject reverseGeocodeJObjectResponse = JObject.Parse(reverseGeocodeJsonResponse);
if (reverseGeocodeJObjectResponse.Count >= 3 &&
reverseGeocodeJObjectResponse["status"]?.ToString().ToLower() != "ok")
{
throw new Exception($"Error: {reverseGeocodeJObjectResponse["error_message"]}");
}
string city = string.Empty;
string country = string.Empty;
//first try to find a city and country where "types": ["locality","political"] in "address_components"
if (reverseGeocodeJObjectResponse["results"] is not null)
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where "types": ["locality","political"] in "address_components"
if (result["types"] is not null
&& result["types"].Count() > 1
&& result["types"][0] is not null
&& string.Equals(result["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& result["types"][1] is not null
&& string.Equals(result["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
if (result["address_components"] is not null)
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"] is not null
&& addressComponent["types"].Count() > 1
&& addressComponent["types"][0] is not null
&& string.Equals(addressComponent["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& addressComponent["types"][1] is not null
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"] is null
? string.Empty
: addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
//try to find a country where "types": ["country","political"] in "address_components"
if (result["types"] is not null
&& result["types"].Count() > 1
&& result["types"][0] is not null
&& string.Equals(result["types"][0].ToString(), "country",
StringComparison.InvariantCultureIgnoreCase)
&& result["types"][1] is not null
&& string.Equals(result["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
if (result["address_components"] is not null)
{
foreach (JToken addressComponent in result["address_components"])
{
country = addressComponent["long_name"] is null
? string.Empty
: addressComponent["long_name"].ToString();
country = country.Replace("'", "''");
}
}
}
}
}
//if city was not found
if (string.IsNullOrWhiteSpace(city))
{
if (reverseGeocodeJObjectResponse["results"] is not null)
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where type of "address_components" is "plus_code"
if (result["types"] is not null
&& result["types"][0] is not null
&& string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
if (result["address_components"] is not null)
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"] is not null
&& addressComponent["types"].Count() > 1
&& addressComponent["types"][0] is not null
&& string.Equals(addressComponent["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& addressComponent["types"][1] is not null
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"] is null
? string.Empty
: addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
}
}
}
//if city was not found
if (string.IsNullOrWhiteSpace(city))
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where type is "street_address"
if (string.Equals(result["types"][0].ToString(), "street_address",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1 &&
string.Equals(addressComponent["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
}
//if city was not found
if (string.IsNullOrWhiteSpace(city))
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where "types": ["administrative_area_level_3","political"] in "address_components" where type is "plus_code"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "administrative_area_level_3",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
}
//if city was not found
if (string.IsNullOrWhiteSpace(city))
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where "types": ["administrative_area_level_1","political"] in "address_components" where type is "plus_code"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "administrative_area_level_1",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
}
//if city was not found
if (string.IsNullOrWhiteSpace(city))
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where "types": ["route"] in "address_components" where "types": ["administrative_area_level_1", "political"]
if (string.Equals(result["types"][0].ToString(), "route",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "administrative_area_level_1",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
}
//if city was not found
if (string.IsNullOrWhiteSpace(city))
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a city where "type" is "plus_code" and "types": ["political", "sublocality", "sublocality_level_1"] in "address_components"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 2
&& string.Equals(addressComponent["types"][0].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "sublocality",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][2].ToString(), "sublocality_level_1",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
}
//if country was not found
if (string.IsNullOrWhiteSpace(country))
{
foreach (JToken result in reverseGeocodeJObjectResponse["results"])
{
//try to find a country where "type" is "plus_code" and "types": ["country", "political"] in "address_components"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "country",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
country = addressComponent["long_name"].ToString();
country = country.Replace("'", "''");
}
}
}
}
}
Console.WriteLine($"City: {city}, country: {country}");
}
}
}
}
}
class LatLng
{
public string Latitude { get; set; }
public string Longitude { get; set; }
}
}
}
//try to find a city where "types": ["locality","political"] in "address_components"
if (result["types"] is not null
&& result["types"].Count() > 1
&& result["types"][0] is not null
&& string.Equals(result["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& result["types"][1] is not null
&& string.Equals(result["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
if (result["address_components"] is not null)
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"] is not null
&& addressComponent["types"].Count() > 1
&& addressComponent["types"][0] is not null
&& string.Equals(addressComponent["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& addressComponent["types"][1] is not null
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"] is null
? string.Empty
: addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
//try to find a city where "types": ["administrative_area_level_3","political"] in "address_components" where type is "plus_code"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "administrative_area_level_3",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
//try to find a city where type of "address_components" is "plus_code"
if (result["types"] is not null
&& result["types"][0] is not null
&& string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
if (result["address_components"] is not null)
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"] is not null
&& addressComponent["types"].Count() > 1
&& addressComponent["types"][0] is not null
&& string.Equals(addressComponent["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& addressComponent["types"][1] is not null
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"] is null
? string.Empty
: addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
}
//try to find a city where type is "street_address"
if (string.Equals(result["types"][0].ToString(), "street_address",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1 &&
string.Equals(addressComponent["types"][0].ToString(), "locality",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
//try to find a city where "types": ["administrative_area_level_1","political"] in "address_components" where type is "plus_code"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "administrative_area_level_1",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
//try to find a city where "types": ["route"] in "address_components" where "types": ["administrative_area_level_1", "political"]
if (string.Equals(result["types"][0].ToString(), "route",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 1
&& string.Equals(addressComponent["types"][0].ToString(), "administrative_area_level_1",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
//try to find a city where "type" is "plus_code" and "types": ["political", "sublocality", "sublocality_level_1"] in "address_components"
if (string.Equals(result["types"][0].ToString(), "plus_code",
StringComparison.InvariantCultureIgnoreCase))
{
foreach (JToken addressComponent in result["address_components"])
{
if (addressComponent["types"].Count() > 2
&& string.Equals(addressComponent["types"][0].ToString(), "political",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][1].ToString(), "sublocality",
StringComparison.InvariantCultureIgnoreCase)
&& string.Equals(addressComponent["types"][2].ToString(), "sublocality_level_1",
StringComparison.InvariantCultureIgnoreCase))
{
city = addressComponent["long_name"].ToString();
city = city.Replace("'", "''");
}
}
}
If in Visual Studio I just change "Output path", VS will always add target framework to folder structure, like "netcoreapp3.1" ("C:\projects\EFCore\tools\netcoreapp3.1"), in order to avoid this, right click on the project, click on "Edit Project File" and add:
Mostly I was using this web site for my example.
In my case I have created the project C:\projects\ReverseGeoCoding, then open PowerShell, and first, if you don't have EF tool installed, execute following:
dotnet tool install --global dotnet-ef
Go to project folder, like cd "C:\projects\ReverseGeoCoding", and add packages "Microsoft.EntityFrameworkCore.Design" and "MySql.EntityFrameworkCore" like:
I had to add package "Microsoft.EntityFrameworkCore.Design", and I had to reference my "ReverseGeoCoding" project, here is how my "EFCore.csproj" look like: