2010-06-08 26 views
18

Tengo una base de datos llena de direcciones que necesito obtener lat y long, así que quiero recorrerlas y usar Google Geocode para actualizar mi base de datos. Estoy atascado en cuanto a cómo analizar el resultado JSON para conseguir lo que necesito:parse google maps geocode json respuesta al objeto usando Json.Net

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

pensé que simplemente podría construir una clase rápida y utilizar JSON.Net deserializar el resultado, y es tipo de elaboración, pero Creo que estoy soplando en mi estructura de clases:

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

aquí está una muestra de lo que está conseguir regresar de 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 
     } 
     } 
    } 
    } ] 
} 

me falta simple aquí que lo sepa, nadie?

Respuesta

44

yo probamos este, hizo una prueba simple y funcionó (resultados agregados y otros):

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

Su la estructura de datos funciona para mí, pero prefiero definir location.lat y location.lng como decimales. Asimismo, es más fácil tener enumeraciones para el estado de respuesta, los tipos de resultados y los tipos de ubicación. Json.NET deserializará las cadenas a las enumeraciones correctamente. – Mart

+0

Esta línea "resultados públicos [] results {get; set;}" resolvió una publicación simultánea de dos horas. Nunca pensé en poner a otra clase un nivel por encima de la clase de resultados. Gracias. – TrueCoke

+0

@antonio Cool y es el segundo en tomar datos gracias –

20

Puede utilizar un objeto dinámico en lugar de definiendo el objeto.

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

espacio de nombres es -> System.Web.Script.Serialization.JavaScriptSerializer en System.Web.Extensions (en System.Web.Extensions.dll) – JGilmartin

+1

Me encanta la simplicidad de esto. –

+1

Hermoso trabajo ... Intenté esto, funciona bien con .NET Framework 4 (Microsoft.Csharp.dll); mientras que no funciona en .NET Framework 3.5. ¿Alguna idea? – Praveen

3

C# Código Objeto he añadido algunas clases adicionales, no está seguro si son nuevos a la API, pero pensé que esto podría ser útil a alguien.

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

Gracias a JEuvin arriba, yo era capaz de cambiar fácilmente de XML a JSON con algunas modificaciones en el código anterior (en concreto el cambio de lat y lng a decimal o doble) y también tuvo que cambiar a address_components.types string [] para que funcione para mí. Luego refactoré un poco para que las mismas clases puedan deserializarse de XML o Json de manera intercambiable.

Tal vez esto ayude a alguien también ...

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

(editado con la adición de postcode_localities y propiedades partial_match)

+1

Asegúrese de agregar algunos atributos JSON también. Ayuda para las operaciones de js. Personalmente no me gusta usar XML. – JEuvin

0

Asegúrese de que la clase es Serializable, permiten 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; } 
    }