Reputation: 28248
I have a DB full of addresses I need to get lat and long for, so I want to loop through them and use Google Geocode to update my database. I am stuck as to how to parse the JSOn result to get what I need:
var address = "http://maps.google.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false";
var result = new System.Net.WebClient().DownloadString(address);
GoogleGeoCodeResponse test = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(result);
I thought I could simply build a quick class and use JSON.Net to deserialize the result, and it is kind of working but I think I am blowing it on my class structure:
public class GoogleGeoCodeResponse {
public string status { get; set; }
public geometry geometry { get; set; }
}
public class geometry {
public string location_type { get; set; }
public location location { get; set; }
}
public class location {
public string lat {get;set;}
public string lng {get;set;}
}
Here is a sample of what get's returned from Google:
{
"status": "OK",
"results": [ {
"types": [ "street_address" ],
"formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
"address_components": [ {
"long_name": "1600",
"short_name": "1600",
"types": [ "street_number" ]
}, {
"long_name": "Amphitheatre Pkwy",
"short_name": "Amphitheatre Pkwy",
"types": [ "route" ]
}, {
"long_name": "Mountain View",
"short_name": "Mountain View",
"types": [ "locality", "political" ]
}, {
"long_name": "California",
"short_name": "CA",
"types": [ "administrative_area_level_1", "political" ]
}, {
"long_name": "United States",
"short_name": "US",
"types": [ "country", "political" ]
}, {
"long_name": "94043",
"short_name": "94043",
"types": [ "postal_code" ]
} ],
"geometry": {
"location": {
"lat": 37.4219720,
"lng": -122.0841430
},
"location_type": "ROOFTOP",
"viewport": {
"southwest": {
"lat": 37.4188244,
"lng": -122.0872906
},
"northeast": {
"lat": 37.4251196,
"lng": -122.0809954
}
}
}
} ]
}
I am missing simple here I know it, anyone?
Upvotes: 20
Views: 33816
Reputation: 11
Here is a C# implementation based on previous answers (with nullable enabled and JsonPropertyName attributes)
using System.Text.Json.Serialization;
namespace YourNameSpace;
public class GoogleGeoCodeResponse
{
[JsonPropertyName("results")]
public Results[] Results { get; set; } = null!;
[JsonPropertyName("status")]
public string Status { get; set; } = null!;
}
public class Results
{
[JsonPropertyName("address_components")]
public AddressComponent[] AddressComponents { get; set; } = null!;
[JsonPropertyName("formatted_address")]
public string FormattedAddress { get; set; } = null!;
[JsonPropertyName("geometry")]
public Geometry Geometry { get; set; } = null!;
[JsonPropertyName("types")]
public string[] Types { get; set; } = null!;
}
public class AddressComponent
{
[JsonPropertyName("long_name")]
public string LongName { get; set; } = null!;
[JsonPropertyName("short_name")]
public string ShortName { get; set; } = null!;
[JsonPropertyName("types")]
public string[] Types { get; set; } = null!;
}
public class Geometry
{
[JsonPropertyName("bounds")]
public Bounds Bounds { get; set; } = null!;
[JsonPropertyName("location")]
public Location Location { get; set; } = null!;
[JsonPropertyName("location_type")]
public string LocationType { get; set; } = null!;
[JsonPropertyName("viewport")]
public Viewport Viewport { get; set; } = null!;
}
public class Location
{
[JsonPropertyName("lat")]
public double Latitude { get; set; }
[JsonPropertyName("lng")]
public double Longitude { get; set; }
}
public class Viewport
{
[JsonPropertyName("northeast")]
public NorthEast NorthEast { get; set; } = null!;
[JsonPropertyName("southwest")]
public SouthWest SouthWest { get; set; } = null!;
}
public class Bounds
{
[JsonPropertyName("northeast")]
public NorthEast NorthEast { get; set; } = null!;
}
public class NorthEast
{
[JsonPropertyName("lat")]
public double Latitude { get; set; }
[JsonPropertyName("lng")]
public double Longitude { get; set; }
}
public class SouthWest
{
[JsonPropertyName("lat")]
public double Latitude { get; set; }
[JsonPropertyName("lng")]
public double Longitude { get; set; }
}
After that, just use the following to deserialize
JsonSerializer.Deserialize<GoogleGeoCodeResponse>(response.RawJson);
Upvotes: 0
Reputation: 11
Just for an update to this with a much easier method of handling what is wanted, all you need to do is the use the following:
var result = new System.Net.WebClient().DownloadString( <<ENTER ADDRESS URL HERE>> );
dynamic geo = JsonConvert.DeserializeObject(result);
then you can access the latitude with: geo.results[0].geometry.location.lat
Upvotes: 1
Reputation:
Make sure the class is Serializable, allow nullables
[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = true)]
public class GeocodeResponse
{
public GeocodeResponse()
{
// can be empty or you can initiate the properties here
}
[XmlElement("location ")]
[Display(Name = "location ")]
// add json attributes as well
public location location { get; set; }
public string status { get; set; }
}
Upvotes: 0
Reputation: 21
Thanks to JEuvin above, I was able to easily switch from XML to Json with a few mods to the code above (specifically changing lat and lng to decimal or double) and also had to change address_components.types to string[] to get it to work for me. I then refactored a bit so that the same classes can be deserialized from XML or Json interchangeably.
Maybe this will help someone too...
using System;
using System.Xml.Serialization;
[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class GeocodeResponse
{
public GeocodeResponse()
{
}
[XmlElement("result")]
public results[] results { get; set; }
public string status { get; set; }
}
[XmlType(AnonymousType = true)]
public class results
{
public results()
{
}
[XmlElement("address_component")]
public address_component[] address_components { get; set; }
public string formatted_address { get; set; }
public geometry geometry { get; set; }
[XmlElement("type")]
public string[] types { get; set; }
public string[] postcode_localities { get; set; }
public bool partial_match { get; set; }
public string place_id { get; set; }
}
[XmlType(AnonymousType = true)]
public class address_component
{
public address_component()
{
}
public string long_name { get; set; }
public string short_name { get; set; }
[XmlElement("type")]
public string[] types { get; set; }
}
[XmlType(AnonymousType = true)]
public class geometry
{
public geometry()
{
}
public bounds bounds { get; set; }
public location location { get; set; }
public string location_type { get; set; }
public viewport viewport { get; set; }
}
[XmlType(AnonymousType = true)]
public class location
{
public location()
{
}
public double lat { get; set; }
public double lng { get; set; }
}
[XmlType(AnonymousType = true)]
public class viewport
{
public viewport()
{
}
public northeast northeast { get; set; }
public southwest southwest { get; set; }
}
[XmlType(AnonymousType = true)]
public class bounds
{
public bounds()
{
}
public northeast northeast { get; set; }
}
[XmlType(AnonymousType = true)]
public class northeast
{
public northeast()
{
}
public double lat { get; set; }
public double lng { get; set; }
}
[XmlType(AnonymousType = true)]
public class southwest
{
public southwest()
{
}
public double lat { get; set; }
public double lng { get; set; }
}
(edited with addition of postcode_localities and partial_match properties)
Upvotes: 2
Reputation: 1039
C# Object Code I added a few extra classes, not sure if they are new to the API but I thought this might be helpful to someone.
public class GoogleGeoCodeResponse
{
public results[] results { get; set; }
public string status { get; set; }
}
public class results
{
public address_component[] address_components { get; set; }
public string formatted_address { get; set; }
public geometry geometry { get; set; }
public string[] types { get; set; }
}
public class address_component
{
String long_name { get; set; }
String short_name { get; set; }
String types { get; set; }
}
public class geometry
{
public bounds bounds { get; set; }
public location location { get; set; }
public string location_type { get; set; }
public viewport viewport { get; set; }
}
public class location
{
public string lat { get; set; }
public string lng { get; set; }
}
public class viewport
{
public northeast northeast { get; set; }
public southwest southwest { get; set; }
}
public class bounds
{
public northeast northeast { get; set; }
}
public class northeast
{
public string lat { get; set; }
public string lng { get; set; }
}
public class southwest
{
public string lat { get; set; }
public string lng { get; set; }
}
Upvotes: 3
Reputation: 392
You can use a dynamic object rather than defining the object.
public static dynamic GEOCodeAddress(String Address)
{
var address = String.Format("http://maps.google.com/maps/api/geocode/json?address={0}&sensor=false", Address.Replace(" ", "+"));
var result = new System.Net.WebClient().DownloadString(address);
JavaScriptSerializer jss = new JavaScriptSerializer();
return jss.Deserialize<dynamic>(result);
}
Upvotes: 20
Reputation: 526
I tried this, made a simple test and it worked (added results and other):
public class GoogleGeoCodeResponse
{
public string status { get; set; }
public results[] results { get; set; }
}
public class results
{
public string formatted_address { get; set; }
public geometry geometry { get; set; }
public string[] types { get; set; }
public address_component[] address_components { get; set; }
}
public class geometry
{
public string location_type { get; set; }
public location location { get; set; }
}
public class location
{
public string lat { get; set; }
public string lng { get; set; }
}
public class address_component
{
public string long_name { get; set; }
public string short_name { get; set; }
public string[] types { get; set; }
}
Upvotes: 51