fcl-json/pl

From Free Pascal wiki
Jump to navigationJump to search

English (en) polski (pl) русский (ru) 中文(中国大陆) (zh_CN)

Informacje

fcl-json jest implementacją JSON.

Zawiera moduły takie jak:

  • fpjson: moduł podstawowy, który implementuje TJsonData i jego klasy potomne, np. TJsonObject
  • jsonParser: implementuje parser TJsonParser, użyty w przykładzie z JsonViewer poniżej
  • jsonConf: implementuje TJsonConfig, który jest przydatny do odczytu/zapisu danych aplikacji z/do plików
  • jsonScanner: leksykalny analizator źródła JSON
Light bulb  Uwaga: W fpjson dostęp np. do SomeJSONObject.Integers['price'] może wywołać zdarzenie SIGSEGV/Access Violation (naruszenie dostępu), jeśli ta zmienna Integers nie istnieje. Jest to pozornie celowe, patrz [[1]]. Będziesz musiał użyć metody Find (dostępnej od wersji FPC 2.6.2), aby najpierw sprawdzić, czy element ('price' w tym przykładzie) istnieje.

Przesyłanie strumieniowe

fcl-json zawiera moduł "fpjsonrtti", który służy do ładowania obiektów (instancji TObject) z formatu JSON lub do zapisywania ich w formacie JSON.

Zobacz Streaming JSON na krótkim przykładzie.

Przykłady

Pierwsze kroki

uses
  fpjson, jsonparser;

procedure JSONTest;
var
  jData : TJSONData;
  jObject : TJSONObject;
  jArray : TJSONArray;
  s : String;
begin
  
  // jest to tylko minimalna próbka tego, co można zrobić z tym interfejsem API

  // utwórz z ciągu string
  jData := GetJSON('{"Fld1" : "Hello", "Fld2" : 42, "Colors" : ["Red", "Green", "Blue"]}');

  // wyjście jako płaski ciąg string
  s := jData.AsJSON;

  // wyjście jest ładnie sformatowanym JSON
  s := jData.FormatJSON;

  // rzutowanie jako TJSONObject, aby ułatwić dostęp
  jObject := TJSONObject(jData);

  // pobierz wartość Fld1
  s := jObject.Get('Fld1');

  // zmień wartość Fld2
  jObject.Integers['Fld2'] := 123;

  // pobierz drugi kolor
  s := jData.FindPath('Colors[1]').AsString;

  // dodaj nowy element
  jObject.Add('Happy', True);

  // dodaj nową pod-tablicę
  jArray := TJSONArray.Create;
  jArray.Add('North');
  jArray.Add('South');
  jArray.Add('East');
  jArray.Add('West');
  jObject.Add('Directions', jArray);

end;

Przenoszenie elementów

uses
  Classes, TypInfo, fpjson, jsonparser;

procedure JSONItems(Info: TStrings);
var
  jData : TJSONData;
  jItem : TJSONData;
  i, j: Integer;
  object_name, field_name, field_value, object_type, object_items: String;
begin
  jData := GetJSON('{"A":{"field1":0, "field2": false},"B":{"field1":0, "field2": false}}');

  for i := 0 to jData.Count - 1 do
  begin
    jItem := jData.Items[i];
 
    object_type := GetEnumName(TypeInfo(TJSONtype), Ord(jItem.JSONType));
    object_name := TJSONObject(jData).Names[i];
    WriteStr(object_items, jItem.Count);
 
    Info.Append('object type: ' + object_type + '|object name: ' + object_name + '|number of fields: ' + object_items);
 
    for j := 0 to jItem.Count - 1 do
    begin
      field_name := TJSONObject(jItem).Names[j];
      field_value := jItem.FindPath(TJSONObject(jItem).Names[j]).AsString;
 
      Info.Append(field_name + '|' + field_value);
    end;
  end;
 
  jData.Free;
end;

Zapisz/wczytaj pozycję/rozmiar okna dialogowego

uses
  jsonConf;

procedure TfmMain.SaveOptionsPos;
var
  c: TJSONConfig;
begin
  c:= TJSONConfig.Create(Nil);
  try
    c.Filename:= 'form.cfg';
    c.SetValue('/dialog/max', WindowState=wsMaximized);
    if WindowState<>wsMaximized then
    begin
      c.SetValue('/dialog/posx', Left);
      c.SetValue('/dialog/posy', Top);
      c.SetValue('/dialog/sizex', Width);
      c.SetValue('/dialog/sizey', Height);
    end;
  finally
    c.Free;
  end;
end;

procedure TfmMain.LoadOptionsPos;
var
  nLeft, nTop, nW, nH: Integer;
  c: TJSONConfig;
begin
  c:= TJSONConfig.Create(Nil);
  try
    c.Filename:= 'form.cfg';

    nLeft:= c.GetValue('/dialog/posx', Left);
    nTop:= c.GetValue('/dialog/posy', Top);
    nW:= c.GetValue('/dialog/sizex', Width);
    nH:= c.GetValue('/dialog/sizey', Height);
    SetBounds(nLeft, nTop, nW, nH);

    if c.GetValue('/dialog/max', false) then
      WindowState:= wsMaximized;
  finally
    c.Free;
  end;
end;

W pliku form.cf zapisze się struktura JSON podobna do tej: { "dialog" : { "max" : false, "posx" : 141, "posy" : 247, "sizex" : 320, "sizey" : 240 } }

Zapisz/wczytaj TStringList

//Przykład ścieżki: '/list_find'

procedure SLoadStringsFromFile(cfg: TJsonConfig; const path: String; List: TStrings);
var
  i: Integer;
  s: UnicodeString;
begin
  List.Clear;
  for i:= 0 to OptMaxHistoryItems-1 do
  begin
    s:= cfg.GetValue(path+'/'+inttostr(i), '');
    if s='' then
      Break;
    List.Add(Utf8Encode(s));
  end;
end;

procedure SSaveStringsToFile(cfg: TJsonConfig; const path: String; List: TStrings);
var
  i: Integer;
  s: String;
begin
  for i:= 0 to OptMaxHistoryItems-1 do
  begin
    if i<List.Count then
      s:= List[i]
    else
      s:= '';
    cfg.SetDeleteValue(path+'/'+inttostr(i), Utf8Decode(s), '');
  end;
end;

Przykład z JsonViewer

Przykład użycia można znaleźć w narzędziu Lazarus jsonviewer (znajdującym się w lazarus/tools/jsonviewer). W szczególności, ta część narzędzia pokazuje, jak używać json:

procedure TMainForm.OpenFile(Const AFileName : String);
var
  S : TFileStream;
  P : TJSONParser;
  D : TJSONData;
begin
  S:=TFileStream.Create(AFileName,fmOpenRead);
  try
    P:=TJSONParser.Create(S);
    try
      P.Strict:=FStrict;
      D:=P.Parse;
    finally
      P.Free;
    end;
  finally
    S.Free;
  end;
  FFileName:=AFileName;
  SetCaption;
  FreeAndNil(FRoot);
  FRoot:=D;
  ShowJSONDocument;
end;

procedure TMainForm.ShowJSONDocument;
begin
  with TVJSON.Items do
  begin
    BeginUpdate;
    try
      TVJSON.Items.Clear;
      SHowJSONData(Nil,FRoot);
      with TVJSON do
        if (Items.Count>0) and Assigned(Items[0]) then
        begin
          Items[0].Expand(False);
          Selected:=Items[0];
        end;
    finally
      EndUpdate;
    end;
  end;
end;

procedure TMainForm.ShowJSONData(AParent : TTreeNode; Data : TJSONData);
var
  N,N2 : TTreeNode;
  I : Integer;
  D : TJSONData;
  C : String;
  S : TStringList;
begin
  N:=Nil;
  if Assigned(Data) then
  begin
    case Data.JSONType of
      jtArray,
      jtObject:
        begin
          if (Data.JSONType=jtArray) then
            C:=SArray
          else
            C:=SObject;
          N:=TVJSON.Items.AddChild(AParent,Format(C,[Data.Count]));
          S:=TstringList.Create;
          try
            for I:=0 to Data.Count-1 do
              if Data.JSONtype=jtArray then
                S.AddObject(IntToStr(I),Data.items[i])
              else
                S.AddObject(TJSONObject(Data).Names[i],Data.items[i]);
            if FSortObjectMembers and (Data.JSONType=jtObject) then
              S.Sort;
            for I:=0 to S.Count-1 do
            begin
              N2:=TVJSON.Items.AddChild(N,S[i]);
              D:=TJSONData(S.Objects[i]);
              N2.ImageIndex:=ImageTypeMap[D.JSONType];
              N2.SelectedIndex:=ImageTypeMap[D.JSONType];
              ShowJSONData(N2,D);
            end
          finally
            S.Free;
          end;
        end;
      jtNull:
        N:=TVJSON.Items.AddChild(AParent,SNull);
      else
        N:=TVJSON.Items.AddChild(AParent,Data.AsString);
    end;
    if Assigned(N) then
    begin
      N.ImageIndex:=ImageTypeMap[Data.JSONType];
      N.SelectedIndex:=ImageTypeMap[Data.JSONType];
      N.Data:=Data;
    end;
  end;
end;

FpcTwit

Biblioteka Przykłady komponentów i kodu wykorzystuje JSON do wysyłania/odbierania danych.

Zobacz też