Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: xinyiman - Novembre 18, 2014, 11:48:01 am

Titolo: Leggere dati da formato
Inserito da: xinyiman - Novembre 18, 2014, 11:48:01 am
Ciao ragazzi, una domanda scema, qual'è il modo più veloce di recuperare i dati da questo formato
Codice: [Seleziona]
{
"personaggi" : [
{
"val1" : "pippo",
"val2" : "2014-11-18T10:25:38.486320Z",
"val3" : 1,
"val4" : 2
},
{
"val1" : "pluto",
"val2" : "2014-11-18T10:25:38.486320Z",
"val3" : 1,
"val4" : 2
},
{
"val1" : "minni",
"val2" : "2014-11-18T10:25:38.486320Z",
"val3" : 1,
"val4" : 2
}
]
}
Titolo: Re:Leggere dati da formato
Inserito da: Legolas - Novembre 18, 2014, 03:40:55 pm
Sembrerebbe in formato JSON (http://wiki.freepascal.org/JSON)
Non l'ho mai usato, ma Lazarus e fpc dovrebbero avere units che lo gestiscono
Titolo: Re:Leggere dati da formato
Inserito da: KiokoKenda - Novembre 18, 2014, 06:06:18 pm
si, confermo che si tratta di un json
dai un occhio qui: http://www.lazaruspascal.it/index.php?page=107
Titolo: Re:Leggere dati da formato
Inserito da: Stilgar - Novembre 18, 2014, 10:41:58 pm
Si è JSon.
E FreePascal ha le sue librerie.
fpjson: per la struttura degli oggetti letti dal json
jsonparser: per leggerli.

più veloce?
Codice: [Seleziona]
procedure TJSonDataProcessor.ParseFile;
var
  Parser: TJSONParser;
  FS: TFileStream;
begin
  try
    try
      FS := TFileStream.Create(FileName, fmOpenRead);
    except
      on E: Exception do
      begin
        FLogger.Error(E.Message);
      end;
    end;
    if assigned(fs) then
    begin
      Parser := TJSONParser.Create(fs);
      FJSonRoot := Parser.Parse;
    end;
  finally
    FreeAndNil(Parser);
    FreeAndNil(FS);
  end;
end;

Abbastranza veloce?
Codice: [Seleziona]
procedure TSectionProcessor.ProcessSection(JSonSection: TJSONObject);
var
  Value: TJSONData;
begin
  Value := JSonSection.Find('text');
  if assigned(Value) then
  begin
    Value.AsString := doTranslate(Value.AsString);
    sleep(random(10));
  end;
  Value := JSonSection.Find('name');
  if assigned(Value) then
  begin
    Value.AsString := doTranslate(Value.AsString);
    sleep(random(10));
  end;
  Value := JSonSection.Find('alignment');
  if assigned(Value) then
  begin
    Value.Value := doTranslate(Value.AsString);
    sleep(random(10));
  end;
  Value := JSonSection.Find('description');
  if assigned(Value) then
  begin
    Value.AsString := doTranslate(Value.AsString);
    sleep(random(10));
  end;
  Value := JSonSection.Find('sections');
  if (assigned(Value)) then
  begin
    if (Value.JSONType = jtArray) then
      ProcessSections(Value as TJSONArray)
    else if (Value.JSONType = jtObject) then
      ProcessSection(Value as TJSONObject);
  end;
end;

Per leggere in modo "selettivo" i nodi.
Alla fine è un albero quello che vai a navigare.

Spero di averti dato qualche dritta utile ;)

Stilgar
Titolo: Re:Leggere dati da formato
Inserito da: xinyiman - Novembre 19, 2014, 07:46:16 am
Grazie proverò, perchè io avevo provato con la guida scritta da Nomorelogic

ma ho questi errori:

Codice: [Seleziona]
superobject.pas(122,18) Error: No matching implementation for interface method "IUnknown.QueryInterface(constref TGuid,out <Formal type>):LongInt; CDecl;" found
superobject.pas(122,18) Error: No matching implementation for interface method "IUnknown._AddRef:LongInt; CDecl;" found
superobject.pas(122,18) Error: No matching implementation for interface method "IUnknown._Release:LongInt; CDecl;" found
superobject.pas(811,1) Fatal: There were 3 errors compiling module, stopping
Titolo: Re:Leggere dati da formato
Inserito da: xinyiman - Novembre 19, 2014, 08:51:03 am
Stilgar, mi sa che non ho capito qualcosa. Mi fai un esempio di come leggere l'esempio che ho fatto e di visualizzarlo con delle showmessage?

Grazie
Titolo: Re:Leggere dati da formato
Inserito da: nomorelogic - Novembre 19, 2014, 02:54:44 pm
quella guida usava una libreria esterna, non faceva parte dei sorgenti fpc

in questo documento ci sono degli esempi (anche) per json
http://www.freepascal.org/~michael/articles/webdata/webdata.pdf (http://www.freepascal.org/~michael/articles/webdata/webdata.pdf)
Titolo: Re:Leggere dati da formato
Inserito da: Stilgar - Novembre 20, 2014, 01:33:35 am
Allora, l'idea del json è quella di un albero.
Quando fai il parse ottieni la root.
Codice: [Seleziona]

  IJsONVisitor = interface
    ['{547B45C9-1EF1-4E5F-9223-E2B9031AC7A8}']
    procedure visit(Value: TJSONData);
    procedure visitIntegerNumber(Value: TJSONIntegerNumber);
    procedure visitInt64Number(Value: TJSONInt64Number);
    procedure visitFloatNumber(Value: TJSONFloatNumber);
    procedure visitString(Value: TJSONString);
    procedure visitBoolean(Value: TJSONBoolean);
    procedure visitNull(Value: TJSONNull);
    procedure visitArray(Value: TJSONArray);
    procedure visitObject(Value: TJSONObject);
  end;


  { TJSonDataProcessor }

  TJSonDataProcessor = class(TAbstractProcessor, IJsONVisitor)
  private
    FFileName: string;
    procedure SetFileName(AValue: string);
  protected
    FJSonRoot: TJSONData;
  protected
    procedure visit(Value: TJSONData); virtual;
    procedure visitIntegerNumber(Value: TJSONIntegerNumber); virtual;
    procedure visitInt64Number(Value: TJSONInt64Number); virtual;
    procedure visitFloatNumber(Value: TJSONFloatNumber); virtual;
    procedure visitString(Value: TJSONString); virtual;
    procedure visitBoolean(Value: TJSONBoolean); virtual;
    procedure visitNull(Value: TJSONNull); virtual;
    procedure visitArray(Value: TJSONArray); virtual;
    procedure visitObject(Value: TJSONObject); virtual;
  public
    procedure ParseFile;
    procedure SaveFile;
    property FileName: string read FFileName write SetFileName;
  public
    procedure process; virtual; abstract;
  end;
Codice: [Seleziona]

{ TJSonDataProcessor }

procedure TJSonDataProcessor.SetFileName(AValue: string);
begin
  if FFileName = AValue then
    Exit;
  FFileName := AValue;
end;

procedure TJSonDataProcessor.visit(Value: TJSONData);
begin
  case Value.JSONType of
    jtArray: visitArray(Value as TJSONArray);
    jtBoolean: visitBoolean(Value as TJSONBoolean);
    jtNull: visitNull(Value as TJSONNull);
    jtObject: visitObject(Value as TJSONObject);
    jtNumber:
    begin
      case (Value as TJSONNumber).NumberType of
        ntFloat:
          visitFloatNumber(Value as TJSONFloatNumber);
        ntInteger:
          visitIntegerNumber(Value as TJSONIntegerNumber);
        ntInt64:
          visitInt64Number(Value as TJSONInt64Number);
        else
          raise EInvalidCast.Create('Number type not recognized');
      end;
    end;
    jtString: visitString(Value as TJSONString);
  end;
end;

procedure TJSonDataProcessor.visitIntegerNumber(Value: TJSONIntegerNumber);
begin

end;

procedure TJSonDataProcessor.visitInt64Number(Value: TJSONInt64Number);
begin

end;

procedure TJSonDataProcessor.visitFloatNumber(Value: TJSONFloatNumber);
begin

end;

procedure TJSonDataProcessor.visitString(Value: TJSONString);
begin

end;

procedure TJSonDataProcessor.visitBoolean(Value: TJSONBoolean);
begin

end;

procedure TJSonDataProcessor.visitNull(Value: TJSONNull);
begin

end;

procedure TJSonDataProcessor.visitArray(Value: TJSONArray);
var
  idx: integer;
begin
  for idx := 0 to Value.Count - 1 do
  begin
    visit(Value.Items[idx]);
  end;
end;

procedure TJSonDataProcessor.visitObject(Value: TJSONObject);
begin

end;


procedure TJSonDataProcessor.ParseFile;
var
  Parser: TJSONParser;
  FS: TFileStream;
begin
  try
    try
      FS := TFileStream.Create(FileName, fmOpenRead);
    except
      on E: Exception do
      begin
        FLogger.Error(E.Message);
      end;
    end;
    if assigned(fs) then
    begin
      Parser := TJSONParser.Create(fs);
      FJSonRoot := Parser.Parse;
    end;
  finally
    FreeAndNil(Parser);
    FreeAndNil(FS);
  end;
end;

procedure TJSonDataProcessor.SaveFile;
var
  newFileName, originalFileName: string;
  FS: TFileStream;
  pretty: TJSONPrettyPrinter;
begin
  originalFileName := FFileName;
  //newFileName := ExpandFileName(originalFileName);
  //newFileName := Copy(newFileName, 1, Length(newFileName) - length('.json')) + '.en.json';
  //RenameFile(FFileName, newFileName);
  newFileName := ExpandFileName(originalFileName);
  newFileName := Copy(newFileName, 1, Length(newFileName) - length('.json')) + '.it.json';
  FS := TFileStream.Create(newFileName, fmCreate);
  pretty := TJSONPrettyPrinter.Create;
  pretty.Target := FS;
  pretty.print(FJSonRoot);
  FreeAndNil(pretty);
end;

Codice: [Seleziona]
  { TStructureProcessor }

  TStructureProcessor = class(TJSonDataProcessor)
  protected
    procedure ProcessFile(aName: TJSONStringType);
    procedure ProcessChildren(value: TJSONObject);
    procedure ProcessChildrens(JSonSection: TJSONArray);
    procedure visitObject(Value: TJSONObject); override;
  public
    procedure process; virtual;
  end;
Codice: [Seleziona]
{ TStructureProcessor }

procedure TStructureProcessor.ProcessFile(aName: TJSONStringType);
var
  p: TDataProcessor;
  targetFileName: string;
begin
  p := TDataProcessor.Create;
  targetFileName := ExpandFileName(ExtractFileDir(ExpandFileName(FileName)) + PathDelim + aName);
  p.FileName := targetFileName;
  P.LangSource := self.LangSource;
  P.LangTarget := self.LangTarget;
  FLogger.Info('Process file '+targetFileName);
  p.process;
  FreeAndNil(p);
end;

procedure TStructureProcessor.ProcessChildren(value: TJSONObject);
var
  aValue: TJSONData;
  index: integer;
begin
  aValue := Value.Find('file');
  if assigned(aValue) then
  begin
    ProcessFile(aValue.AsString);
  end;
  aValue := Value.Find('children');
  if Assigned(aValue) then
  begin
    begin
      if (aValue.JSONType = jtArray) then
        ProcessChildrens(aValue as TJSONArray)
      else if (Value.JSONType = jtObject) then
        ProcessChildren(aValue as TJSONObject);
    end;
  end;
end;

procedure TStructureProcessor.ProcessChildrens(JSonSection: TJSONArray);
var
  idx: integer;
  obj: TJSONObject;
begin
  for idx := 0 to JSonSection.Count - 1 do
  begin
    ProcessChildren(JSonSection.Objects[idx]);
  end;
end;

procedure TStructureProcessor.visitObject(Value: TJSONObject);
var
  aValue: TJSONData;
  index: integer;

begin
  aValue := Value.Find('file');
  if assigned(aValue) then
  begin
    ProcessFile(aValue.AsString);
  end;
  aValue := Value.Find('children');
  if Assigned(aValue) then
  begin
    begin
      if (aValue.JSONType = jtArray) then
        ProcessChildrens(aValue as TJSONArray)
      else if (Value.JSONType = jtObject) then
        ProcessChildren(aValue as TJSONObject);
    end;
  end;
end;

procedure TStructureProcessor.process;
begin
  ParseFile;
  visit(FJSonRoot);
  SaveFile;
end;
 

Credo che, anche se ancora non funziona a dovere il mio programma, queste classi possono essere un esempio su come processare file json.

;)

Stilgar
Titolo: Re:Leggere dati da formato
Inserito da: xinyiman - Novembre 20, 2014, 07:47:02 am
Mi hanno risposto a questo link, così se serve trovate la soluzione


http://forum.lazarus.freepascal.org/index.php?topic=26509.msg162997#msg162997