ago 312010
 

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

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)