Difference between revisions of "fcl-json/ru"

From Lazarus wiki
Jump to navigationJump to search
 
(38 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
{{fcl-json}}
 
{{fcl-json}}
 +
 
= Информация =
 
= Информация =
  
Line 11: Line 12:
 
* jsonScanner: лексический анализатор исходников json
 
* jsonScanner: лексический анализатор исходников json
  
Note: In fpjson, accessing e.g. SomeJSONObject.Integers['price'] may give a SIGSEGV/Access Violation if that integer variable does not exist. This is apparently intentional, see [http://bugs.freepascal.org/view.php?id=22273].
+
{{Notefpjson, доступ, например, <code>SomeJSONObject.Integers['цена']</code> может дать Нарушение SIGSEGV/Access, если это целая переменная не существует. Это, очевидно, сделано намеренно, см [[http://bugs.freepascal.org/view.php?id=22273]].}}
 
   
 
   
You'd have to use the Find method (available since FPC 2.6.2) to first check if the element ('price' in this example) exists.
+
Вы должны были бы использовать метод Find (доступен в FPC 2.6.2), чтобы сначала проверить, существует ли элемент ('цена' в данном примере).
  
= Streaming =
+
= Маршаллинг =
fcl-json contains the unit "fpjsonrtti" which is used to load objects (TObject instances) from or save them to JSON format.
+
fcl-json содержит юнит "fpjsonrtti", который используется для загрузки из объектов или сохранения их в формате JSON(экземпляров TObject).
  
See [[Streaming JSON]] for a short example.
+
Смотрите [[Streaming JSON/ru|Streaming JSON]] для короткого примера.
  
= Examples =
+
= Примеры =
  
  
== Getting Started ==
+
== Итак, начнём ==
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
  
uses fpjson, jsonparser;
+
USES fpjson, jsonparser;
  
procedure JSONTest;
+
PROCEDURE JSONTest;
var
+
VAR
 
   jData : TJSONData;
 
   jData : TJSONData;
 
   jObject : TJSONObject;
 
   jObject : TJSONObject;
 
   jArray : TJSONArray;
 
   jArray : TJSONArray;
 
   s : string;
 
   s : string;
begin
+
BEGIN 
 
+
   // это лишь минимальный пример того, что можно сделать с помощью этого API
   // this is only a minimal sampling of what can be done with this API
 
  
   // create from string
+
   // создать строки JSON
   jData := GetJSON('{"Fld1" : "Hello", "Fld2" : 42, "Colors" : ["Red", "Green", "Blue"]}');
+
   jData := GetJSON('{"поле1" : "Привет", "поле2" : 42, "Цвет" : ["Красный", "Зелёный", "Голубой"]}');
  
   // output as a flat string
+
   // вывести как плоскую строку
 
   s := jData.AsJSON;
 
   s := jData.AsJSON;
  
   //  output as nicely formatted JSON
+
   //  вывести замечательно-отформатированный JSON
 
   s := jData.FormatJSON;
 
   s := jData.FormatJSON;
  
   // cast as TJSONObject to make access easier
+
   // передан как TJSONObject для простого доступа
 
   jObject := TJSONObject(jData);
 
   jObject := TJSONObject(jData);
  
   // retrieve value of Fld1
+
   // передача значения ключа "поле1"
   s := jObject.Get('Fld1');
+
   s := jObject.Get('поле1');
  
   // change value of Fld2
+
   // установка значения ключа "поле2"
   jObject.Integers['Fld2'] := 123;
+
   jObject.Integers['поле2'] := 123;
  
   // retrieve the second color
+
   // передача второго цвета
   s := jData.FindPath('Colors[1]').AsString;
+
   s := jData.FindPath('Цвет[1]').AsString;
  
   // add a new element
+
   // добавить новый элемент
 
   jObject.Add('Happy', True);
 
   jObject.Add('Happy', True);
  
   // add a new sub-array
+
   // передать новый подмассив
 
   jArray := TJSONArray.Create;
 
   jArray := TJSONArray.Create;
   jArray.Add('North');
+
   jArray.Add('Север');
   jArray.Add('South');
+
   jArray.Add('Юг');
   jArray.Add('East');
+
   jArray.Add('Восток');
   jArray.Add('West');
+
   jArray.Add('Запад');
   jObject.Add('Directions', jArray);
+
   jObject.Add('Направление', jArray);
 +
 
 +
END;
 +
</syntaxhighlight>
  
 +
== Перемещение пунктов ==
 +
 +
<syntaxhighlight lang=pascal>
 +
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;
 
end;
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Save/load dialog position/size ==
+
== Сохранение/загрузка позиции/размера диалога ==
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
uses jsonConf;
+
USES jsonConf;
  
procedure TfmMain.SaveOptionsPos;
+
PROCEDURE TfmMain.SaveOptionsPos;
var
+
VAR
 
   c: TJSONConfig;
 
   c: TJSONConfig;
begin
+
BEGIN
 
   c:= TJSONConfig.Create(nil);
 
   c:= TJSONConfig.Create(nil);
   try
+
   TRY
 
     c.Filename:= GetAppPath(cFileHistory);
 
     c.Filename:= GetAppPath(cFileHistory);
 
     c.SetValue('/dialog/max', WindowState=wsMaximized);
 
     c.SetValue('/dialog/max', WindowState=wsMaximized);
 
     if WindowState<>wsMaximized then
 
     if WindowState<>wsMaximized then
     begin
+
     BEGIN
 
       c.SetValue('/dialog/posx', Left);
 
       c.SetValue('/dialog/posx', Left);
 
       c.SetValue('/dialog/posy', Top);
 
       c.SetValue('/dialog/posy', Top);
 
       c.SetValue('/dialog/sizex', Width);
 
       c.SetValue('/dialog/sizex', Width);
 
       c.SetValue('/dialog/sizey', Height);
 
       c.SetValue('/dialog/sizey', Height);
     end;
+
     END;
   finally
+
   FINALLY
 
     c.Free;
 
     c.Free;
   end;
+
   END;
end;
+
END;
  
 
procedure TfmMain.LoadOptionsPos;
 
procedure TfmMain.LoadOptionsPos;
Line 123: Line 160:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Save/load TStringList ==
+
== Сохранение/загрузка TStringList ==
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
//Example of path: '/list_find'
+
//Пример пути: '/list_find'
  
procedure SLoadStringsFromFile(cfg: TJsonConfig; const path: string; List: TStrings);
+
PROCEDURE SLoadStringsFromFile(cfg: TJsonConfig; const path: string; List: TStrings);
var
+
VAR
 
   i: integer;
 
   i: integer;
 
   s: UnicodeString;
 
   s: UnicodeString;
begin
+
BEGIN
 
   List.Clear;
 
   List.Clear;
   for i:= 0 to OptMaxHistoryItems-1 do
+
   FOR i:= 0 TO OptMaxHistoryItems-1 DO
   begin
+
   BEGIN
 
     s:= cfg.GetValue(path+'/'+inttostr(i), '');
 
     s:= cfg.GetValue(path+'/'+inttostr(i), '');
     if s='' then Break;
+
     IF s='' THEN break;
 
     List.Add(Utf8Encode(s));
 
     List.Add(Utf8Encode(s));
   end;
+
   END;
end;
+
END;
  
procedure SSaveStringsToFile(cfg: TJsonConfig; const path: string; List: TStrings);
+
PROCEDURE SSaveStringsToFile(cfg: TJsonConfig; const path: string; List: TStrings);
var
+
VAR
 
   i: integer;
 
   i: integer;
 
   s: string;
 
   s: string;
begin
+
BEGIN
   for i:= 0 to OptMaxHistoryItems-1 do
+
   FOR i:= 0 TO OptMaxHistoryItems-1 DO
   begin
+
   BEGIN
     if i<List.Count then
+
     IF i<List.Count THEN
 
       s:= List[i]
 
       s:= List[i]
     else
+
     ELSE
 
       s:= '';
 
       s:= '';
 
     cfg.SetDeleteValue(path+'/'+inttostr(i), Utf8Decode(s), '');
 
     cfg.SetDeleteValue(path+'/'+inttostr(i), Utf8Decode(s), '');
   end;
+
   END;
end;
+
END;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== From JsonViewer ==
+
== Использование JsonViewer ==
  
Example usage can be found in the Lazarus jsonviewer tool (located in lazarus/tools/jsonviewer).
+
Пример использования можно найти в инструментах Lazarus: jsonviewer (расположенный в lazarus/tools/jsonviewer). В частности, эта часть инструмента показывает, как использовать JSON:
In particular, this part of the tool shows how to use json:
 
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
procedure TMainForm.OpenFile(Const AFileName : String);
+
PROCEDURE TMainForm.OpenFile(Const AFileName : String);
 
+
VAR
Var
 
 
   S : TFileStream;
 
   S : TFileStream;
 
   P : TJSONParser;
 
   P : TJSONParser;
 
   D : TJSONData;
 
   D : TJSONData;
begin
+
BEGIN
 
   S:=TFileStream.Create(AFileName,fmOpenRead);
 
   S:=TFileStream.Create(AFileName,fmOpenRead);
   try
+
   TRY
 
     P:=TJSONParser.Create(S);
 
     P:=TJSONParser.Create(S);
     try
+
     TRY
 
       P.Strict:=FStrict;
 
       P.Strict:=FStrict;
 
       D:=P.Parse;
 
       D:=P.Parse;
     finally
+
     FINALLY
 
       P.Free;
 
       P.Free;
     end;
+
     END;
   finally
+
   FINALLY
 
     S.Free;
 
     S.Free;
   end;
+
   END;
 
   FFileName:=AFileName;
 
   FFileName:=AFileName;
 
   SetCaption;
 
   SetCaption;
Line 188: Line 223:
 
   FRoot:=D;
 
   FRoot:=D;
 
   ShowJSONDocument;
 
   ShowJSONDocument;
end;
+
END;
  
procedure TMainForm.ShowJSONDocument;
+
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;
  
begin
+
PROCEDURE TMainForm.ShowJSONData(AParent : TTreeNode; Data : TJSONData);
  With TVJSON.Items do
+
VAR
    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;
 
   N,N2 : TTreeNode;
 
   I : Integer;
 
   I : Integer;
Line 219: Line 252:
 
   C : String;
 
   C : String;
 
   S : TStringList;
 
   S : TStringList;
 
+
BEGIN
begin
 
 
   N:=Nil;
 
   N:=Nil;
   if Assigned(Data) then
+
   IF Assigned(Data) THEN
     begin
+
     BEGIN
     Case Data.JSONType of
+
     CASE Data.JSONType OF
 
       jtArray,
 
       jtArray,
 
       jtObject:
 
       jtObject:
         begin
+
         BEGIN
         If (Data.JSONType=jtArray) then
+
         IF (Data.JSONType=jtArray) THEN
 
           C:=SArray
 
           C:=SArray
         else
+
         ELSE
 
           C:=SObject;
 
           C:=SObject;
 
         N:=TVJSON.Items.AddChild(AParent,Format(C,[Data.Count]));
 
         N:=TVJSON.Items.AddChild(AParent,Format(C,[Data.Count]));
 
         S:=TstringList.Create;
 
         S:=TstringList.Create;
         try
+
         TRY
           For I:=0 to Data.Count-1 do
+
           FOR I:=0 TO Data.Count-1 DO
             If Data.JSONtype=jtArray then
+
             IF Data.JSONtype=jtArray THEN
 
               S.AddObject(IntToStr(I),Data.items[i])
 
               S.AddObject(IntToStr(I),Data.items[i])
             else
+
             ELSE
 
               S.AddObject(TJSONObject(Data).Names[i],Data.items[i]);
 
               S.AddObject(TJSONObject(Data).Names[i],Data.items[i]);
           If FSortObjectMembers and (Data.JSONType=jtObject) then
+
           IF FSortObjectMembers and (Data.JSONType=jtObject) THEN
 
             S.Sort;
 
             S.Sort;
           For I:=0 to S.Count-1 do
+
           FOR I:=0 TO S.Count-1 DO
             begin
+
             BEGIN
            N2:=TVJSON.Items.AddChild(N,S[i]);
+
              N2:=TVJSON.Items.AddChild(N,S[i]);
            D:=TJSONData(S.Objects[i]);
+
              D:=TJSONData(S.Objects[i]);
            N2.ImageIndex:=ImageTypeMap[D.JSONType];
+
              N2.ImageIndex:=ImageTypeMap[D.JSONType];
            N2.SelectedIndex:=ImageTypeMap[D.JSONType];
+
              N2.SelectedIndex:=ImageTypeMap[D.JSONType];
            ShowJSONData(N2,D);
+
              ShowJSONData(N2,D);
             end
+
             END
         finally
+
         FINALLY
 
           S.Free;
 
           S.Free;
         end;
+
         END;
         end;
+
         END;
 
       jtNull:
 
       jtNull:
 
         N:=TVJSON.Items.AddChild(AParent,SNull);
 
         N:=TVJSON.Items.AddChild(AParent,SNull);
     else
+
     ELSE
 
       N:=TVJSON.Items.AddChild(AParent,Data.AsString);
 
       N:=TVJSON.Items.AddChild(AParent,Data.AsString);
     end;
+
     END;
     If Assigned(N) then
+
     IF Assigned(N) THEN
       begin
+
       BEGIN
      N.ImageIndex:=ImageTypeMap[Data.JSONType];
+
        N.ImageIndex:=ImageTypeMap[Data.JSONType];
      N.SelectedIndex:=ImageTypeMap[Data.JSONType];
+
        N.SelectedIndex:=ImageTypeMap[Data.JSONType];
      N.Data:=Data;
+
        N.Data:=Data;
       end;
+
       END;
     end;
+
     END;
end;   
+
END;   
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== FpcTwit ==
+
Библиотека [[Components_and_Code_examples#Networking|Components and Code examples]] использует JSON для передачи/приема данных.
  
The [[FPC Applications/Projects Gallery#FPCTwit|fpctwit]] library makes use of JSON to send/receive data.
+
==Изменение формата чисел с плавающей запятой==
  
= See also =
+
Вопрос: моя программа генерирует и записывает данные в файл JSON. Я использую метод <code>FormatJSON()</code>, чтобы сделать вывод более читабельным. Меня не совсем устраивает, как выглядят числа с плавающей точкой:
An article covering use of XML and JSON in FreePascal: [http://www.freepascal.org/~michael/articles/webdata/webdata.pdf PDF]
+
 
 +
"coordinates" : [
 +
      5.5978631048365003E+001,
 +
      2.2100000000000000E+002
 +
]
 +
 
 +
Я хочу видеть нормальную форму:
 +
 
 +
"coordinates" : [
 +
      55.978631048365003,
 +
      221.0
 +
]
 +
 
 +
Ответ: (пользователи форума '''y.ivanov''', '''rvk''', '''wp'''):
 +
<syntaxhighlight lang="pascal">
 +
{$mode objfpc}{$h+}
 +
uses
 +
  fpjson,
 +
  jsonparser,
 +
  SysUtils;
 +
 +
type
 +
  TJSONFloat4Number = class(TJSONFloatNumber)
 +
  protected
 +
    function GetAsString: TJSONStringType; override;
 +
  end;
 +
 +
function TJSONFloat4Number.GetAsString: TJSONStringType;
 +
var
 +
  F: TJSONFloat;
 +
  fs: TFormatSettings;
 +
begin
 +
  fs := DefaultFormatSettings;
 +
  fs.DecimalSeparator := '.';
 +
  F := GetAsFloat;
 +
  Result := FormatFloat('0.0###############', F, fs); // форматирование с вашими предпочтениями
 +
end;
  
[[Package List]]
+
procedure JSONTest;
 +
var
 +
  jData: TJSONData;
 +
begin
 +
  jData := GetJSON('{"coordinates": [5.5978631048365003E+001, 2.2100000000000000E+002]}');
 +
  writeln(jData.FormatJSON);
 +
  jData.Free;
 +
end;
 +
 +
begin
 +
  SetJSONInstanceType(jitNumberFloat, TJSONFloat4Number);
 +
  JSONTest;
 +
  Readln;
 +
end.
 +
</syntaxhighlight>
  
[[Category:FPC]]
+
== Смотрите также ==
[[Category:FCL]]
+
* Статья охватывает использование XML и JSON в Free Pascal: [http://www.freepascal.org/~michael/articles/webdata/webdata.pdf PDF]
[[Category:Packages]]
+
* [[Package List]]
[[Category:JSON]]
 

Latest revision as of 23:07, 6 October 2022

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

Информация

fcl-json реализация стандарта JSON.

Пакет содержит юниты:

  • fpjson: базовый юнит, который реализует TJsonData и их потомков, например TJsonObject
  • JsonParser: реализует TJsonParser, используется в примере ниже
  • jsonConf: реализует TJsonConfig, что удобно для чтения/записи данных файлов приложения
  • jsonScanner: лексический анализатор исходников json
Light bulb  Примечание: В fpjson, доступ, например, SomeJSONObject.Integers['цена'] может дать Нарушение SIGSEGV/Access, если это целая переменная не существует. Это, очевидно, сделано намеренно, см [[1]].

Вы должны были бы использовать метод Find (доступен в FPC 2.6.2), чтобы сначала проверить, существует ли элемент ('цена' в данном примере).

Маршаллинг

fcl-json содержит юнит "fpjsonrtti", который используется для загрузки из объектов или сохранения их в формате JSON(экземпляров TObject).

Смотрите Streaming JSON для короткого примера.

Примеры

Итак, начнём

USES fpjson, jsonparser;

PROCEDURE JSONTest;
VAR
   jData : TJSONData;
   jObject : TJSONObject;
   jArray : TJSONArray;
   s : string;
BEGIN   
   // это лишь минимальный пример того, что можно сделать с помощью этого API

   // создать строки JSON
   jData := GetJSON('{"поле1" : "Привет", "поле2" : 42, "Цвет" : ["Красный", "Зелёный", "Голубой"]}');

   // вывести как плоскую строку
   s := jData.AsJSON;

   //  вывести замечательно-отформатированный JSON
   s := jData.FormatJSON;

   // передан как TJSONObject для простого доступа
   jObject := TJSONObject(jData);

   // передача значения ключа "поле1"
   s := jObject.Get('поле1');

   // установка значения ключа "поле2"
   jObject.Integers['поле2'] := 123;

   // передача второго цвета
   s := jData.FindPath('Цвет[1]').AsString;

   // добавить новый элемент
   jObject.Add('Happy', True);

   // передать новый подмассив
   jArray := TJSONArray.Create;
   jArray.Add('Север');
   jArray.Add('Юг');
   jArray.Add('Восток');
   jArray.Add('Запад');
   jObject.Add('Направление', jArray);

END;

Перемещение пунктов

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;

Сохранение/загрузка позиции/размера диалога

USES jsonConf;

PROCEDURE TfmMain.SaveOptionsPos;
VAR
  c: TJSONConfig;
BEGIN
  c:= TJSONConfig.Create(nil);
  TRY
    c.Filename:= GetAppPath(cFileHistory);
    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:= GetAppPath(cFileHistory);

    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;

Сохранение/загрузка TStringList

//Пример пути: '/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;

Использование JsonViewer

Пример использования можно найти в инструментах Lazarus: jsonviewer (расположенный в lazarus/tools/jsonviewer). В частности, эта часть инструмента показывает, как использовать 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;

Библиотека Components and Code examples использует JSON для передачи/приема данных.

Изменение формата чисел с плавающей запятой

Вопрос: моя программа генерирует и записывает данные в файл JSON. Я использую метод FormatJSON(), чтобы сделать вывод более читабельным. Меня не совсем устраивает, как выглядят числа с плавающей точкой:

"coordinates" : [
     5.5978631048365003E+001,
     2.2100000000000000E+002
]

Я хочу видеть нормальную форму:

"coordinates" : [
     55.978631048365003,
     221.0
]

Ответ: (пользователи форума y.ivanov, rvk, wp):

{$mode objfpc}{$h+}
uses
  fpjson,
  jsonparser,
  SysUtils;
 
type
  TJSONFloat4Number = class(TJSONFloatNumber)
  protected
    function GetAsString: TJSONStringType; override;
  end;
 
function TJSONFloat4Number.GetAsString: TJSONStringType;
var
  F: TJSONFloat;
  fs: TFormatSettings;
begin
  fs := DefaultFormatSettings;
  fs.DecimalSeparator := '.';
  F := GetAsFloat;
  Result := FormatFloat('0.0###############', F, fs); // форматирование с вашими предпочтениями
end;

procedure JSONTest;
var
  jData: TJSONData;
begin
  jData := GetJSON('{"coordinates": [5.5978631048365003E+001, 2.2100000000000000E+002]}');
  writeln(jData.FormatJSON);
  jData.Free;
end;
 
begin
  SetJSONInstanceType(jitNumberFloat, TJSONFloat4Number);
  JSONTest;
  Readln;
end.

Смотрите также

  • Статья охватывает использование XML и JSON в Free Pascal: PDF
  • Package List