"Geocodificação é o processo de conversão de endereços (como "1600 Amphitheatre Parkway, Mountain View, CA") em coordenadas geográficas (como latitude 37.423021 e longitude -122.083739), que você pode usar para colocar marcadores ou posicionar o mapa. A Google Geocoding API fornece uma maneira direta de acessar um geocodificador por meio de uma solicitação HTTP. Além disso, o serviço permite que você realize a operação inversa (transformar coordenadas em endereços); esse processo é conhecido como "geocodificação reversa"."
Uma solitação de geocoding deve ter basicamente os seguinte formato:
http://maps.googleapis.com/maps/api/geocode/output?parametersonde output significa o formato do retorno dos dados, que pode ser json(recomendável) ou xml.
Além disso são obrigatórios os parâmetros:
- address — o endereço que você deseja geocodificar
ou
latlng — o valor textual de latitude/longitude para o qual você deseja obter o endereço mais próximo.
- sensor — indica se a solicitação de geocodificação vem ou não de um dispositivo com sensor de localização. Esse valor deve ser true ou false.
A resposta da requisição contém dois elementos raiz:
- status - contém metadados sobre a solicitação. Consulte os Códigos de status no site.
- results - contém uma matriz de informações de endereços geocodificados e informações geométricas.
Eu implementei uma biblioteca bem simples que suporta os dois formatos de resposta: json e xml.
Para interpretar o resultando em json, utilizei a biblioteca lkjson, pois, já tinha utilizado a mesma em outros projetos e achei bastante simples de usar, mais existem outras opções como o SuperObject e Delphi Web Utils.
Para interpretar o formato xml optei por utilizar o Xml Data Binding do delphi, que através de um wizard cria classes tipadas a partir do arquivos xml, deixando todo o processo de transformação transparente.
Basicamente o que fiz foi o seguinte, efetuei uma requisição no serviço de geocodificação no formato xml e salvei os dados retornados em um arquivo xml. Em seguida, utilizei o Xml Data Binding para transformar esse xml em classes. Essas classes são o resultado final da solicitação, seja ela em json ou xml.
Quando a requisição é no formato xml, é utilizado o binding do XmlDocument:
class function TGoogleApiGeoXml.XmlToGeocodeResponse(const AXmlText: String): IGeocodeResponse;
var
vXmlDocument: IXMLDocument;
begin
vXmlDocument := TXMLDocument.Create(nil);
vXmlDocument.LoadFromXml(UTF8Encode(AXmlText));
Result := vXmlDocument.GetDocBinding('GeocodeResponse', TGeocodeResponse) as IGeocodeResponse;
end;
Quando a requisição é no formato json, escrevi o parser "na unha", que retorna o mesmo tipo de objeto da solicitação em xml, deixando a aplicação que consome o serviço utilizar o mesmo sem se importar se é xml ou json.
function TGoogleApiGeoJson.ConvertFromJson(const AJsonText: String): IGeocodeResponse;
var
vJsonResponse: TlkJSONobject;
vResults: TlkJSONbase;
begin
Result := TGeocodeResponse.NewGeocodeResponse;
vJsonResponse := TlkJSONobject(TlkJSON.ParseText(UTF8Encode(AJsonText)));
try
vResults := TlkJSONlist(TlkJSONlist(vJsonResponse.Field['results']).Field['address_components']).Items[0];
ParseStatus(Result, vJsonResponse);
ParseType(Result, vResults);
ParseFormattedAddress(Result, vResults);
ParseAddresses(Result, vResults);
ParseGeometry(Result, vResults);
finally
vJsonResponse.Free;
end;
end;
Na sistema em si, o único código que ele precisa executar é esse:
var
vResponse: IGeocodeResponse;
begin
vResponse := TGoogleApiGeocodeDownload.GetGeocode("http://maps.googleapis.com/maps/api/geocode/json_ou_xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true_ou_false");
//Lógica que utiliza a resposta da solicitação
O implementação do método GetGeocode é bastante simples também, ele faz uma requisição HTTP utilizando indy conforme abaixo
class function TGoogleApiGeocodeDownload.HttpGet(Url: String): String;
var
lHTTP: TIdHTTP;
lStream: TStringStream;
begin
lHTTP := TIdHTTP.Create(nil);
lStream := TStringStream.Create(EmptyStr);
try
lHTTP.Get(Url, lStream);
lStream.Position := 0;
Result := UTF8Decode(lStream.DataString);
finally
FreeAndNil(lHTTP);
FreeAndNil(lStream);
end;
end;
E de acordo com o formato dos dados faz uma chamada ao parser correspondente para retornar o objeto.
class function TGoogleApiGeocodeDownload.GetGeocode(AUrl: String): IGeocodeResponse;
var
vDados: String;
vFormato: TOutputFormat;
begin
vFormato := DiscoverFormat(AUrl);
vDados := HttpGet(AUrl);
case vFormato of
Json: Result := TGoogleApiGeoJson.JsonToGeocodeResponse(vDados);
Xml : Result := TGoogleApiGeoXml.XmlToGeocodeResponse(vDados);
end;
end;
Mais informações sobre limitações de uso e sobre os parâmetros utilizados na requisição HTTP podem ser encontrados aqui.
O código fonte completo com exemplo de como utilizar pode ser acessado aqui no meu bitbucket.
Um abraço e fique ligado nos próximos posts.
Nenhum comentário:
Postar um comentário