20

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?

7 Answers 7

51

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; }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Your data structure works for me, but I prefer defining location.lat and location.lng as decimals. Likewise is it easier to have enums for the response status, result types and location types. Json.NET will deserialize strings to enums correctly.
This line "public results[] results { get; set; }" solved a two hour roadblock. I never thought of putting another class a level above the results class. Thank you.
@antonio Cool and it's just second to take data thanks
20

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);
    }

5 Comments

namespace is -> System.Web.Script.Serialization.JavaScriptSerializer in System.Web.Extensions (in System.Web.Extensions.dll)
I love the simplicity of this.
Beautiful work.. I tried this, works fine with .NET Framework 4(Microsoft.Csharp.dll); whereas not working in .NET Framework 3.5. Any idea?
Thanks all, I feel all warm and fuzzy. @user1671639 DownloadString() came in with .net 4.5 you can use other methods to get the result of the web call using other "Get a Web Page as a String" methods ... the same is true for the JavaScriptSerializer .... however there is an open source JSON implementation for C# out there also.
@matt.j.crawford Thanks. One suggestion, please mention this in your answer. Would be helpful to others.
3

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; }
    }

Comments

2

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)

1 Comment

Make sure you add some JSON attributes as well. It helps for js operations. I personally dislike using XML.
1

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

Comments

0

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; }
  }

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.