Difference between revisions of "Streaming JSON/ru"

From Free Pascal wiki
Jump to navigationJump to search
 
(28 intermediate revisions by 5 users not shown)
Line 8: Line 8:
  
 
== Общие положения и условия ==
 
== Общие положения и условия ==
Loading and storing (streaming) FPC object data is done with the fpjsonrtti unit. Furthermore, the Classes unit is useful (see below for details).
+
Загрузка и хранение (маршалинг) FPC данных объекта осуществляется с помощью юнита "fpjsonrtti". Кроме того, может пригодиться класс Class в этом юните (см ниже).
Загрузка и хранение (маршалинг) FPC данных объекта осуществляется с помощью юнита fpjsonrttiN. Кроме того, может пригоlиться Class в юните (см ниже).
 
  
 
В связи с этим оператор USES должен содержать, по крайней мере, эти два юнита:
 
В связи с этим оператор USES должен содержать, по крайней мере, эти два юнита:
<syntaxhighlight>USES Classes, fpjsonrtti;</syntaxhighlight>
+
<syntaxhighlight lang="pascal">USES Classes, fpjsonrtti;</syntaxhighlight>
  
 
В настоящее время (май 2014 г.) есть некоторые отличия от потоковой системы Free Pascal с ??_предположительно_ JavaScript ??:
 
В настоящее время (май 2014 г.) есть некоторые отличия от потоковой системы Free Pascal с ??_предположительно_ JavaScript ??:
Line 26: Line 25:
 
{
 
{
 
   "id"    : 123,                                                // Integer
 
   "id"    : 123,                                                // Integer
   "объект"    : { "имя": "Привет, мир!" },                          // Object
+
   "obj"    : { "name": "Привет, мир!" },                          // Object
   "колл"  : [ { "имя": "Объект 1" }, { "имя": "Объект 2" } ], // два объекта  TCollection  
+
   "coll"  : [ { "name": "Объект 1" }, { "name": "Объект 2" } ], // два объекта  TCollection  
   "строки": [ "привет 1", "привет 2" ]                            // список строк
+
   "strings": [ "привет 1", "привет 2" ]                            // список строк
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
Это может быть выполнено в Free Pascal с использованием констант следующим образом:
 
Это может быть выполнено в Free Pascal с использованием констант следующим образом:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
const JSON_TESTDATA =
 
const JSON_TESTDATA =
 
'{'+LineEnding+
 
'{'+LineEnding+
 
'  "id": 123,'+LineEnding+
 
'  "id": 123,'+LineEnding+
'  "объект": { "имя": "Hello world!" },'+LineEnding+
+
'  "obj": { "name": "Привет, Мир!" },'+LineEnding+
'  "колл": [ { "имя": "Объект 1" }, { "имя": "Объект 2" } ],'+LineEnding+
+
'  "coll": [ { "name": "Объект 1" }, { "name": "Объект 2" } ],'+LineEnding+
'  "строки": [ "привет 1", "привет 2" ]'+LineEnding+
+
'  "strings": [ "привет 1", "привет 2" ]'+LineEnding+
 
'}';
 
'}';
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 45: Line 45:
 
== Структура данных ==
 
== Структура данных ==
  
В качестве базового класса для обслуживания данных существует класс [[TPersistent]] из юнита Classes, так как для них и всех подклассов должен быть создан [[Runtime Type Information (RTTI)|Laufzeit-Typinformationen]] (<abbr title="Runtime Type Information">RTTI</abbr>). Это совершенно необходимо для маршаллинга. Поскольку fpjsonrtti  не интегрирован в систему маршаллинга, любого другого класса, должна быть указана опция компилятора <source enclose="none">{$M+}</source>, для использования.
+
В качестве базового класса для обслуживания данных существует класс [[TPersistent]] из юнита Classes, так как для них и всех подклассов должен быть создан [[Runtime Type Information (RTTI)|Laufzeit-Typinformationen]] (<abbr title="Runtime Type Information">RTTI</abbr>). Это совершенно необходимо для маршаллинга. Поскольку fpjsonrtti  не интегрирован в систему маршаллинга, любого другого класса, должна быть указана опция компилятора '''{$M+}''', для использования.
  
 
Все объекты должны быть доступны как [[Property|property]] для чтения в разделе класса [[Published|published]]. В общем случае (переменная) должна быть доступна для чтения и записи непосредственно в поле данных. Если вы хотите, конечно, могут быть использованы методы getter и setter.
 
Все объекты должны быть доступны как [[Property|property]] для чтения в разделе класса [[Published|published]]. В общем случае (переменная) должна быть доступна для чтения и записи непосредственно в поле данных. Если вы хотите, конечно, могут быть использованы методы getter и setter.
Line 51: Line 51:
 
Для структуры JSON результаты определении класса представлены ниже.
 
Для структуры JSON результаты определении класса представлены ниже.
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
 
TYPE
 
TYPE
 
   TNameObject = CLASS(TCollectionItem) // класс для свойства 'obj' и TCollection  
 
   TNameObject = CLASS(TCollectionItem) // класс для свойства 'obj' и TCollection  
Line 67: Line 67:
 
     fStrings: TStrings;
 
     fStrings: TStrings;
 
   PUBLIC
 
   PUBLIC
     constructor Create;
+
     CONSTRUCTOR Create;
     destructor Destroy; override;
+
     DESTRUCTOR Destroy; override;
   PUBLISHED// all properties have published  
+
   PUBLISHED// все свойства должны быть published
     property id: Integer read fid write fid;
+
     PROPERTY id: Integer read fid write fid;
     property obj: TNameObject read fObj write fObj;
+
     PROPERTY obj: TNameObject read fObj write fObj;
     property coll: TCollection read fColl;
+
     PROPERTY coll: TCollection read fColl;
     property strings: TStrings read fStrings;
+
     PROPERTY strings: TStrings read fStrings;
 
   END;  
 
   END;  
 
</syntaxhighlight>
 
</syntaxhighlight>
  
The class <source enclose="none">TNameObject</source> is of [[TCollectionItem]] derived. So they can both for the property ''obj'' be used as well in the collection. If this is not desired, here two different classes must be defined.
+
Класс <code>TNameObject</code> является потомком [[TCollectionItem]]. Таким образом, они могут оба  для свойства ''obj'' использовать коллекции. Если это не желательно, здесь должны быть определены два различных класса.
  
In the constructor of the class TBaseObject the TCollection and the string list must be created and released in the destructor.
+
В конструкторе класса TBaseObject класс TCollection и список строк должен быть создан конструктором и уничтожен в деструкторе.
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
constructor TBaseObject.Create;
+
CONSTRUCTOR TBaseObject.Create;
begin
+
BEGIN
   // Collection and StringList constructor
+
   // конструктор коллекции и StringList
 
   fColl    := TCollection.Create(TNameObject);
 
   fColl    := TCollection.Create(TNameObject);
 
   fStrings := TStringList.Create;
 
   fStrings := TStringList.Create;
 
   fObj    := TNameObject.Create(nil);
 
   fObj    := TNameObject.Create(nil);
end;
+
END;
  
destructor TBaseObject.Destroy;
+
DESTRUCTOR TBaseObject.Destroy;
begin
+
BEGIN
   // Collection and StringList destructor
+
   // деструктор коллекции и StringList
 
   fColl.Free;
 
   fColl.Free;
 
   fStrings.Free;
 
   fStrings.Free;
 
   fObj.Free;
 
   fObj.Free;
   inherited Destroy;
+
   INHERITED Destroy;
end;
+
END;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
If you do not want any more functionality in the data classes, their definition is already done.
+
Если вы не хотите больше функций для данных классов, их определение закончено.
  
== Load JSON ==
+
== Загрузка JSON ==
  
With the method <source enclose="none">Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject);</source> in the [[TJSONDeStreamer]] class you can assign JSON data directly to an ''existing'' object. Before you call the method, you must create TJSONDeStreamer and the target object.
+
С помощью метода <syntaxhighlight inline lang=pascal>Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject);</syntaxhighlight> в классе [[TJSONDeStreamer]] вы можете присвоить данные в формате JSON непосредственно ''существующему'' объекту; перед тем, как вызвать этот метод, вы должны создать TJSONDeStreamer и целевой объект.
  
The following method loads the data from the JSON structure <source enclose="none">JSON_TESTDATA</source> in the o object and then writes the current values ​​of the properties on the console.
+
Следующий метод загружает данные из структуры JSON <syntaxhighlight inline lang=pascal>JSON_TESTDATA</syntaxhighlight> в объект "о" и затем выводит текущие значения свойств в консоли.
  
<syntaxhighlight>
+
<syntaxhighlight lang="pascal">
procedure DeStreamTest;
+
PROCEDURE DeStreamTest;
var
+
VAR
 
   DeStreamer: TJSONDeStreamer;
 
   DeStreamer: TJSONDeStreamer;
 
   o: TBaseObject;
 
   o: TBaseObject;
 
   no: TNameObject;
 
   no: TNameObject;
 
   s: String;
 
   s: String;
begin
+
BEGIN
   WriteLn('DeStream test');
+
   WriteLn('тест DeStream');
 
   WriteLn('======================================');
 
   WriteLn('======================================');
  
   // DeStreamer object and target object create
+
   // объект DeStreamer и целевой объект
 
   DeStreamer := TJSONDeStreamer.Create(nil);
 
   DeStreamer := TJSONDeStreamer.Create(nil);
 
   o := TBaseObject.Create;
 
   o := TBaseObject.Create;
   try
+
   TRY
     // Load JSON data in the object o
+
     // загрузка данных JSON в объект o
 
     DeStreamer.JSONToObject(JSON_TESTDATA, o);
 
     DeStreamer.JSONToObject(JSON_TESTDATA, o);
 
     // ID
 
     // ID
 
     WriteLn(o.id);
 
     WriteLn(o.id);
     // Object Name
+
     // имя объекта
 
     WriteLn(o.obj.name);  
 
     WriteLn(o.obj.name);  
     // Print the names of all objects
+
     // напечатать имена всех объектов
 
     for TCollectionItem(no) in o.coll do
 
     for TCollectionItem(no) in o.coll do
 
       Writeln(no.name);
 
       Writeln(no.name);
     // output all strings
+
     // вывести все строки
 
     for s in o.strings do
 
     for s in o.strings do
 
       WriteLn(s);
 
       WriteLn(s);
  
   // Cleanup
+
   // очистка
   finally
+
   FINALLY
 
     o.Destroy;
 
     o.Destroy;
 
     DeStreamer.Destroy;
 
     DeStreamer.Destroy;
   end;
+
   END;
end;
+
END;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Saving JSON ==
+
== Сохранение JSON ==
  
To convert an object into a JSON text, the class [[TJSONStreamer]] is used. Here the method <syntaxhighlight enclose="none">Function ObjectToJSONString(AObject : TObject) : TJSONStringType;</syntaxhighlight> is used.
+
Для преобразования объекта в текст JSON, используется класс [[TJSONStreamer]]. Здесь используется метод <syntaxhighlight inline lang=pascal> FUNCTION ObjectToJSONString(AObject : TObject) : TJSONStringType;</syntaxhighlight>.
  
In the following procedure, an object is created, filled with the test data, and then converted to JSON. The order in which the properties are saved cannot be influenced by the programmer.
+
В следующей процедуре, объект создается, заполняется данными теста, а затем преобразуются в формат JSON. Порядок, в котором сохраняются свойства не могут зависеть от программиста.
  
Finally, the JSON text is printed to the console.
+
И, наконец, текст JSON выводится на консоль.
  
<syntaxhighlight>
+
<syntaxhighlight lang="Pascal">
procedure StreamTest;
+
PROCEDURE StreamTest;
var
+
VAR
 
   Streamer: TJSONStreamer;
 
   Streamer: TJSONStreamer;
 
   o: TBaseObject;
 
   o: TBaseObject;
 
   JSONString: String;
 
   JSONString: String;
begin
+
BEGIN
 
   WriteLn('Stream test');
 
   WriteLn('Stream test');
 
   WriteLn('======================================');
 
   WriteLn('======================================');
Line 164: Line 164:
 
   Streamer := TJSONStreamer.Create(nil);
 
   Streamer := TJSONStreamer.Create(nil);
 
   o := TBaseObject.Create;
 
   o := TBaseObject.Create;
   try
+
   TRY
     // Data set
+
     // установка данных
 
     o.id := 123;
 
     o.id := 123;
     o.obj.name := 'Hello world!';
+
     o.obj.name := 'Привет, мир!';
     TNameObject(o.coll.Add).name := 'Object 1';
+
     TNameObject(o.coll.Add).name := 'Объект 1';
     TNameObject(o.coll.Add).name := 'Object 2';
+
     TNameObject(o.coll.Add).name := 'Объект 2';
     o.strings.Add('Hello 1');
+
     o.strings.Add('Привет 1');
     o.strings.Add('Hello 2');
+
     o.strings.Add('Привет 2');
  
     Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // Save strings as JSON array
+
     Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // сохранение строки в JSON
     // JSON convert and output
+
     // конвертация вывод и JSON
 
     JSONString := Streamer.ObjectToJSONString(o);
 
     JSONString := Streamer.ObjectToJSONString(o);
 
     WriteLn(JSONString);
 
     WriteLn(JSONString);
  
   // Cleanup
+
   // очистка
   finally
+
   FINALLY
 
     o.Destroy;
 
     o.Destroy;
 
     Streamer.Destroy;
 
     Streamer.Destroy;
   end;
+
   END;
end;
+
END;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Conclusion ==
+
== Вывод ==
  
With the presented knowledge, simple and complex JSON data structures can be loaded in your Free Pascal programs. Should any pre- or postprocessing of he JSON data be necessary, the text data can be initially loaded into a JSON data structure (with the class[[TJSONParser]] from the Unit [[jsonparser]]) and then manipulated with the Unit [[fpJSON]].
+
С помощью представленного знания, простые и сложные структуры данных JSON могут быть загружены в ваши программы на Free Pascal. Если необходима какая-либо пред- или постобработка данных JSON, текстовые данные могут быть изначально загружены в структуру данных в формате JSON (классом [[TJSONParser]] из юнита [[jsonparser]]), а затем можно обрабатывать с помощью юнита [[fpJSON]].
  
The TJSONStreamer's Options property can be used to control the representation of your own data structures in JSON.
+
Опции свойства TJSONStreamer могут быть использованы для управления представлением ваших собственных структур данных в формате JSON.
  
== See Also ==
+
== Смотрите также ==
* [[JSON]]
+
* [[JSON/ru|JSON]]
* [[fcl-json]]
+
* [[fcl-json/ru|fcl-json]]
 
* [[Streaming components]]
 
* [[Streaming components]]
  
== Notes & References ==
+
== Примечания & Ссылки ==
 
# <div id="ref1">http://lists.freepascal.org/fpc-pascal/2013-January/036254.html</div>
 
# <div id="ref1">http://lists.freepascal.org/fpc-pascal/2013-January/036254.html</div>
 
# <div id="ref2>http://lists.lazarus.freepascal.org/pipermail/lazarus/2011-January/058878.html</div>
 
# <div id="ref2>http://lists.lazarus.freepascal.org/pipermail/lazarus/2011-January/058878.html</div>
 
[[Category:Tutorials]]
 
[[Category:JSON]]
 
[[Category:JSON/ru]]
 
[[Category:JavaScript]]
 

Latest revision as of 17:18, 6 August 2022

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

Light bulb  Примечание: Эта статья является перевод статьи с английского Streaming_JSON от 2014-10-02, которая была переведена с помощью Google Translate с немецкого (оригинал). Понятно, что результат перевода может быть ужасным, вполне может требоваться ручная корректировка. Убедительная просьба не использовать автоматический перевод без окончательной обработки

JSON(JavaScript Object Notation) является текстовым, стандартизированным форматом данных. Как следует из названия, JSON документы являются правильным кодом JavaScript, где они могут быть непосредственно преобразованы в объекты JavaScript. Но сам по себе JSON может быть использован независимо от используемого языка программирования для обмена данными.

В этом руководстве объясняется, как загрузить данные в формате JSON в программе Free Pascal для обработки. Оно также объясняет, как преобразовать данные FPC в формате JSON (например, чтобы отправить их на веб-сервер).

Общие положения и условия

Загрузка и хранение (маршалинг) FPC данных объекта осуществляется с помощью юнита "fpjsonrtti". Кроме того, может пригодиться класс Class в этом юните (см ниже).

В связи с этим оператор USES должен содержать, по крайней мере, эти два юнита:

USES Classes, fpjsonrtti;

В настоящее время (май 2014 г.) есть некоторые отличия от потоковой системы Free Pascal с ??_предположительно_ JavaScript ??:

  • Данные в формате JSON чувствительны к регистру. Таким образом, свойства объектов Free Pascal, как свойства JSON должны быть написаны с правильным регистром.
  • Нет свойств, которые могут быть определены как DefineProperties. Нельзя сохранить ссылки на методы (обработчики событий).2
  • TCollection и TStrings может быть использован в качестве замены массивов.

Демо-версия программы предоставляется с исходным кодом Free Pascal Compiler (в папке /packages/fcl-json/examples).

В качестве примера, мы приведём пример со следующими данными JSON:

{
  "id"     : 123,                                                // Integer
  "obj"    : { "name": "Привет, мир!" },                          // Object
  "coll"   : [ { "name": "Объект 1" }, { "name": "Объект 2" } ], // два объекта  TCollection 
  "strings": [ "привет 1", "привет 2" ]                            // список строк
}

Это может быть выполнено в Free Pascal с использованием констант следующим образом:

const JSON_TESTDATA =
'{'+LineEnding+
'  "id": 123,'+LineEnding+
'  "obj": { "name": "Привет, Мир!" },'+LineEnding+
'  "coll": [ { "name": "Объект 1" }, { "name": "Объект 2" } ],'+LineEnding+
'  "strings": [ "привет 1", "привет 2" ]'+LineEnding+
'}';

Структура данных

В качестве базового класса для обслуживания данных существует класс TPersistent из юнита Classes, так как для них и всех подклассов должен быть создан Laufzeit-Typinformationen (RTTI). Это совершенно необходимо для маршаллинга. Поскольку fpjsonrtti не интегрирован в систему маршаллинга, любого другого класса, должна быть указана опция компилятора {$M+}, для использования.

Все объекты должны быть доступны как property для чтения в разделе класса published. В общем случае (переменная) должна быть доступна для чтения и записи непосредственно в поле данных. Если вы хотите, конечно, могут быть использованы методы getter и setter.

Для структуры JSON результаты определении класса представлены ниже.

TYPE
  TNameObject = CLASS(TCollectionItem) // класс для свойства 'obj' и TCollection 
  PRIVATE
    fName: String;
  PUBLISHED
    property name: String read fName write fName;
  END;  

  TBaseObject = CLASS(TPersistent)  // класс для структуры JSON
  PRIVATE
    fid: Integer;
    fObj: TNameObject;
    fColl: TCollection;
    fStrings: TStrings;
  PUBLIC
    CONSTRUCTOR Create;
    DESTRUCTOR Destroy; override;
  PUBLISHED// все свойства должны быть published
    PROPERTY id: Integer read fid write fid;
    PROPERTY obj: TNameObject read fObj write fObj;
    PROPERTY coll: TCollection read fColl;
    PROPERTY strings: TStrings read fStrings;
  END;

Класс TNameObject является потомком TCollectionItem. Таким образом, они могут оба для свойства obj использовать коллекции. Если это не желательно, здесь должны быть определены два различных класса.

В конструкторе класса TBaseObject класс TCollection и список строк должен быть создан конструктором и уничтожен в деструкторе.

CONSTRUCTOR TBaseObject.Create;
BEGIN
  // конструктор коллекции и StringList
  fColl    := TCollection.Create(TNameObject);
  fStrings := TStringList.Create;
  fObj     := TNameObject.Create(nil);
END;

DESTRUCTOR TBaseObject.Destroy;
BEGIN
  // деструктор коллекции и StringList
  fColl.Free;
  fStrings.Free;
  fObj.Free;
  INHERITED Destroy;
END;

Если вы не хотите больше функций для данных классов, их определение закончено.

Загрузка JSON

С помощью метода Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject); в классе TJSONDeStreamer вы можете присвоить данные в формате JSON непосредственно существующему объекту; перед тем, как вызвать этот метод, вы должны создать TJSONDeStreamer и целевой объект.

Следующий метод загружает данные из структуры JSON JSON_TESTDATA в объект "о" и затем выводит текущие значения свойств в консоли.

PROCEDURE DeStreamTest;
VAR
  DeStreamer: TJSONDeStreamer;
  o: TBaseObject;
  no: TNameObject;
  s: String;
BEGIN
  WriteLn('тест DeStream');
  WriteLn('======================================');

  // объект DeStreamer и целевой объект 
  DeStreamer := TJSONDeStreamer.Create(nil);
  o := TBaseObject.Create;
  TRY
    // загрузка данных JSON в объект o
    DeStreamer.JSONToObject(JSON_TESTDATA, o);
    // ID
    WriteLn(o.id);
    // имя объекта
    WriteLn(o.obj.name); 
    // напечатать имена всех объектов
    for TCollectionItem(no) in o.coll do
      Writeln(no.name);
    // вывести все строки
    for s in o.strings do
      WriteLn(s);

  // очистка
  FINALLY
    o.Destroy;
    DeStreamer.Destroy;
  END;
END;

Сохранение JSON

Для преобразования объекта в текст JSON, используется класс TJSONStreamer. Здесь используется метод FUNCTION ObjectToJSONString(AObject : TObject) : TJSONStringType;.

В следующей процедуре, объект создается, заполняется данными теста, а затем преобразуются в формат JSON. Порядок, в котором сохраняются свойства не могут зависеть от программиста.

И, наконец, текст JSON выводится на консоль.

PROCEDURE StreamTest;
VAR
  Streamer: TJSONStreamer;
  o: TBaseObject;
  JSONString: String;
BEGIN
  WriteLn('Stream test');
  WriteLn('======================================');

  Streamer := TJSONStreamer.Create(nil);
  o := TBaseObject.Create;
  TRY
    // установка данных
    o.id := 123;
    o.obj.name := 'Привет, мир!';
    TNameObject(o.coll.Add).name := 'Объект 1';
    TNameObject(o.coll.Add).name := 'Объект 2';
    o.strings.Add('Привет 1');
    o.strings.Add('Привет 2');

    Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // сохранение строки в JSON
    // конвертация вывод и JSON
    JSONString := Streamer.ObjectToJSONString(o);
    WriteLn(JSONString);

  // очистка
  FINALLY
    o.Destroy;
    Streamer.Destroy;
  END;
END;

Вывод

С помощью представленного знания, простые и сложные структуры данных JSON могут быть загружены в ваши программы на Free Pascal. Если необходима какая-либо пред- или постобработка данных JSON, текстовые данные могут быть изначально загружены в структуру данных в формате JSON (классом TJSONParser из юнита jsonparser), а затем можно обрабатывать с помощью юнита fpJSON.

Опции свойства TJSONStreamer могут быть использованы для управления представлением ваших собственных структур данных в формате JSON.

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

Примечания & Ссылки