Wednesday, September 25, 2013

C# sample for Google Geocoding API (JSON output)




C# Google geocoding API (JSON output) sample


Geocoding is the process of converting addresses (like "300 n state st chicago IL") into geographic coordinates (like latitude 37.423021 and longitude -122.083739), which you can use to place markers or position the map.



The Google Geocoding API provides a direct way to access a these services via an HTTP request.


This service is generally designed for geocoding static (known in advance) addresses for placement of application content on a map;



A Geocoding API request must be of the following form:
http://maps.googleapis.com/maps/api/geocode/output?parameters
where output may be either of the following values:
  • json (recommended) indicates output in JavaScript Object Notation (JSON)
  • xml indicates output as XML
Required parameters
  • address — The address that you want to geocode.       or  latlng — The textual latitude/longitude value for which you wish to obtain the closest, human-readable address. 
  • sensor — Indicates whether or not the geocoding request comes from a device with a location sensor. This value must be either true or false.
JSON Output Formats
http://maps.googleapis.com/maps/api/geocode/json?address=300+n+state+st+chicago+Il&sensor=true&components=country:US
We've left the sensor parameter in this example as a variable true_or_false to emphasize that you must set this value to either true or false explicitly.
The JSON returned by this request is shown below. 
{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "300",
               "short_name" : "300",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "North State Street",
               "short_name" : "N State St",
               "types" : [ "route" ]
            },
            {
               "long_name" : "River North",
               "short_name" : "River North",
               "types" : [ "neighborhood", "political" ]
            },
            {
               "long_name" : "Chicago",
               "short_name" : "Chicago",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Cook",
               "short_name" : "Cook",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "Illinois",
               "short_name" : "IL",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "60654",
               "short_name" : "60654",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "300 North State Street, Chicago, IL 60654, USA",
         "geometry" : {
            "location" : {
               "lat" : 41.8883461,
               "lng" : -87.6288376
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 41.8896950802915,
                  "lng" : -87.6274886197085
               },
               "southwest" : {
                  "lat" : 41.8869971197085,
                  "lng" : -87.63018658029151
               }
            }
         },
         "types" : [ "street_address" ]
      }
   ],
   "status" : "OK"
}

Note that the JSON response contains two root elements:
  • "status" contains metadata on the request. See Status Codes below.
  • "results" contains an array of geocoded address information and geometry information.
Generally, only one entry in the "results" array is returned for address lookups, though the geocoder may return several results when address queries are ambiguous.
Following C# sample queries Google GeoCoding API and parses json response to custom .Net object. We've utilized Json.Net framework to parsing json object. 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.IO;
using System.Net;
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Please enter the address to validate:");
            var address = Console.ReadLine();
            NetGoogleGeocoding geoCoder = new NetGoogleGeocoding();
            var response = geoCoder.GoogleGeocode(address);
            Console.WriteLine("*********** validation complete *****************");
            Console.WriteLine(string.Format("House Number ---- {0}",response.GeoCodes[0].HouseNumber));
            Console.WriteLine(string.Format("Street Address -- {0}",response.GeoCodes[0].StreetAddress));
            Console.WriteLine(string.Format("City ------------ {0}",response.GeoCodes[0].City));
            Console.WriteLine(string.Format("County ---------- {0}",response.GeoCodes[0].County));
            Console.WriteLine(string.Format("State ----------- {0}",response.GeoCodes[0].State));
            Console.WriteLine(string.Format("Zip ------------- {0}",response.GeoCodes[0].Zip));
            Console.WriteLine(string.Format("Country --------- {0}",response.GeoCodes[0].Country));
            Console.WriteLine(string.Format("Full Address ---- {0}",response.GeoCodes[0].FullAddress));
            if (response.GeoCodes[0].Types.Count() > 1)
            {
                Console.WriteLine(string.Format("Types ----------- {0},{1}", response.GeoCodes[0].Types[0], response.GeoCodes[0].Types[1]));
            }
            else
            {
                Console.WriteLine(string.Format("Types ----------- {0}", response.GeoCodes[0].Types[0]));
            }
            Console.WriteLine(string.Format("Location Type---- {0}",response.GeoCodes[0].LocationType));
            Console.WriteLine(string.Format("Latitude -------  {0}",response.GeoCodes[0].Latitude.ToString()));
            Console.WriteLine(string.Format("Longitude-------- {0}",response.GeoCodes[0].Longitude.ToString()));
            Console.WriteLine(string.Format("Status   -------- {0}", response.GeoCodes[0].Status));
            Console.ReadLine();
         }
    }
 /// 
 ///   .Net utility for google geocoding API
 /// 
 public class NetGoogleGeocoding {
        public GeocodeJsonResponse GoogleGeoCodeResponse;
  const string GoogleGeoCodeJsonServiceUrl = "http://maps.googleapis.com/maps/api/geocode/json?address={0}&sensor=true&components=country:US";
        public NetGoogleGeocoding()
        {
            GoogleGeoCodeResponse = new GeocodeJsonResponse()
            {
                GeoCodes = new List()
            };
  }
  /// 
  ///   Performs Geocode and returns Object
  /// 
  ///  
        public GeocodeJsonResponse GoogleGeocode(string address)
        {
            using (var cli = new WebClient())
            {
                var addressToValidate = string.Format(GoogleGeoCodeJsonServiceUrl, HttpUtility.UrlEncode(address));
                var response = cli.DownloadString(new Uri(addressToValidate));
                return HydrateJson(response);
           }
  }
  /// 
  /// generic method to read json values from json string
  /// 
  ///  
  ///  
  ///  
  static string GetJsonNodeValue(JToken token, string field) {
   return token["address_components"].Children().Any(x => x["types"].Values().Contains(field))
        ? token["address_components"].Children().First(x => x["types"].Values().Contains(field))["short_name"].Value()
        : string.Empty;
  }
        GeocodeJsonResponse HydrateJson(string jsonResponse)
        {
   var results = (JObject) JsonConvert.DeserializeObject(jsonResponse);
   foreach(
   var googleGeoCode in
      results["results"].Children().Select(
         token =>
   new Geocode {
      HouseNumber = GetJsonNodeValue(token, "street_number"),
      StreetAddress = GetJsonNodeValue(token, "route"),
      City = GetJsonNodeValue(token, "locality"),
      County = GetJsonNodeValue(token, "administrative_area_level_2"),
      State = GetJsonNodeValue(token, "administrative_area_level_1"),
      Zip = GetJsonNodeValue(token, "postal_code"),
      Country = GetJsonNodeValue(token, "country"),
      FullAddress = token["formatted_address"].Value(),
      Types = token["types"].Values().ToList(),
      LocationType = token["geometry"]["location_type"].Value(),
      Latitude = token["geometry"]["location"]["lat"].Value(),
      Longitude = token["geometry"]["location"]["lng"].Value(),
      Status = string.Format("{0}", token["geometry"]["location_type"].Value())
   })) {
    GoogleGeoCodeResponse.GeoCodes.Add(googleGeoCode);
   }
   return GoogleGeoCodeResponse;
  }
 }

    public class GeocodeJsonResponse
    {
        public List GeoCodes { get; set; }
    }
    public class Geocode
    {
        public string HouseNumber { get; set; }
        public string StreetAddress { get; set; }
        public string City { get; set; }
        public string County { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
        public string Country { get; set; }
        public string FullAddress { get; set; }
        public List Types { get; set; }
        public string LocationType { get; set; }
        public float Latitude { get; set; }
        public float Longitude { get; set; }
        public string Status { get; set; }
    }

}