Buenas,
Vista la estructura JSON en un mensaje anterior, ahora toca realizar el desglose de la misma en Delphi.
Por defecto, Delphi no trae nada para leer/interpretar una estructura JSON, así que tenemos dos opciones, o nos montamos nosotros algo, o miramos lo que ya hay hecho. Como no soy de los que les gusta reinventar la rueda, con una sencilla consulta a la página oficial de JSON vemos que hay varias librerías disponibles que nos realizan la labor. He escogido la JSON Delphi Library debido a que sólo es un .pas (no hay que instalar nada), trae ejemplos de su funcionamiento y su uso no es complicado.
Antes de ver el código de lectura del JSON, vamos a ver dónde lo vamos a almacenar. Para ello he diseñado un par de clases. La primera, TGeoCode, es la clase que controlará todo el resultado JSON:
TAfterGetData = procedure (Sender: TObject; AllData: string) of object; TAfterGetValues = procedure (Sender: TObject; AllValues: TStrings) of object; TGeoCode = class private FDireccion: string; FGeoStatus: string; FGeoList: TObjectList; FBeforeProcess: TNotifyEvent; FAfterProcess: TNotifyEvent; FAfterGetData: TAfterGetData; FAfterGetValues: TAfterGetValues; FData: TStrings; function GetCount: Integer; protected procedure Parse; procedure ShowValues; public constructor Create(Dir: string = ''); virtual; destructor Destroy; override; // realiza la carga del JSON procedure Execute; // inicializa la estructura procedure Clear; // dirección que queremos GeoLocalizar property Direccion: string read FDireccion write FDireccion; // cantidad de GeoLocalizaciones devueltas por el API de Google Maps property Count: Integer read GetCount; // JSON devuelto por el API de Google Maps property Data: TStrings read FData write FData; // *********** propiedades devueltas por la geolocalización *************** // estado de la consulta property GeoStatus: string read FGeoStatus write FGeoStatus; // lista de objetos de la clase TPlace, es decir, cada una de las GeoLocalizaciones // devueltar en el JSON property GeoList: TObjectList read FGeoList write FGeoList; // eventos property BeforeProcess: TNotifyEvent read FBeforeProcess write FBeforeProcess; property AfterProcess: TNotifyEvent read FAfterProcess write FAfterProcess; property AfterGetData: TAfterGetData read FAfterGetData write FAfterGetData; property AfterGetValues: TAfterGetValues read FAfterGetValues write FAfterGetValues; end;
Como vemos, también le he definido 4 eventos, para así poder, en el caso que se quiera, alguna pantalla de espera, cambiar el ratón para decir que se está trabajando, leer la info extraída justo después de que se haga,….. Vamos, para hacer lo que uno buenamente quiera.
La segunda clase es TPlace que contendrá cada una de las GeoLocalizaciones devueltas en la estructura JSON.
TGeoGeometry = record Lat: Real; Lon: Real; end; TAddrComp = record LongName: string; ShortName: string; AddrCompType: TStrings; end; TGeoAddrComp = array of TAddrComp; TPlace = class private FGeoAddrComp: TGeoAddrComp; FGeoFormatedAddr: string; FGeoType: TStrings; FGeoGeometry: TGeoGeometry; public constructor Create; virtual; destructor Destroy; override; property GeoType: TStrings read FGeoType write FGeoType; property GeoFormatedAddr: string read FGeoFormatedAddr write FGeoFormatedAddr; property GeoAddrComp: TGeoAddrComp read FGeoAddrComp write FGeoAddrComp; property GeoGeometry: TGeoGeometry read FGeoGeometry write FGeoGeometry; end;
Ahora ya sólo queda ver cómo se cargaría la estructura JSON en objetos de nuestra clase, o lo que es lo mismo, ver el método Execute de la clase TGeoCode.
Lo primero que tenemos que hacer es crear un objeto de la clase TlkJSONobject el cual se encargará de leer la estructura JSON y montar su estructura interna. Luego sólo tendremos que recorrer esta estructura para ir almacenándola en nuestros objetos.
procedure TGeoCode.Execute; var IdHTTP: TIdHTTP; Str: string; Stream: TStringStream; begin if FDireccion = '' then Exit; if Assigned(FBeforeProcess) then FBeforeProcess(Self); IdHTTP := TIdHTTP.Create(nil); Stream := TStringStream.Create(''); try // sustituimos blancos por signo + Str := AnsiReplaceStr(FDireccion, CHAR_SPACE, CHAR_PLUS); // generamos url con parámetros Str := STR_WEB + Str + STR_SENSOR + STR_REGION; // hacemos petición a la API de Google IdHTTP.Get(Str, Stream); // pasamos de UTF8 a string FData.Text := UTF8ToString(Stream.DataString); if Assigned(FAfterGetData) then FAfterGetData(Self, FData.Text); // realizamos PARSE Parse; // mostramos valores en la lista ShowValues; finally if Assigned(Stream) then FreeAndNil(Stream); if Assigned(IdHTTP) then FreeAndNil(IdHTTP); end; if Assigned(FAfterProcess) then FAfterProcess(Self); end;
En el próximo capítulo veremos cómo funcionan nuestras clases en una aplicación para mostrar los datos recibidos en, por ejemplo, un TValueListEditor.
Puedes descargarte la unit GeoCode desde aquí.
continuará……..
Nos leemos