Difference between revisions of "Streaming JSON/ru"
Prospero78su (talk | contribs) |
|||
(28 intermediate revisions by 5 users not shown) | |||
Line 8: | Line 8: | ||
== Общие положения и условия == | == Общие положения и условия == | ||
− | + | Загрузка и хранение (маршалинг) FPC данных объекта осуществляется с помощью юнита "fpjsonrtti". Кроме того, может пригодиться класс Class в этом юните (см ниже). | |
− | Загрузка и хранение (маршалинг) FPC данных объекта осуществляется с помощью юнита | ||
В связи с этим оператор 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 | ||
− | " | + | "obj" : { "name": "Привет, мир!" }, // Object |
− | " | + | "coll" : [ { "name": "Объект 1" }, { "name": "Объект 2" } ], // два объекта TCollection |
− | " | + | "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+ | ||
− | ' " | + | ' "obj": { "name": "Привет, Мир!" },'+LineEnding+ |
− | ' " | + | ' "coll": [ { "name": "Объект 1" }, { "name": "Объект 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 не интегрирован в систему маршаллинга, любого другого класса, должна быть указана опция компилятора | + | В качестве базового класса для обслуживания данных существует класс [[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; | |
− | + | DESTRUCTOR Destroy; override; | |
− | PUBLISHED// | + | 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; | END; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Класс <code>TNameObject</code> является потомком [[TCollectionItem]]. Таким образом, они могут оба для свойства ''obj'' использовать коллекции. Если это не желательно, здесь должны быть определены два различных класса. | |
− | + | В конструкторе класса TBaseObject класс TCollection и список строк должен быть создан конструктором и уничтожен в деструкторе. | |
− | <syntaxhighlight> | + | <syntaxhighlight lang="Pascal"> |
− | + | CONSTRUCTOR TBaseObject.Create; | |
− | + | BEGIN | |
− | // | + | // конструктор коллекции и StringList |
fColl := TCollection.Create(TNameObject); | fColl := TCollection.Create(TNameObject); | ||
fStrings := TStringList.Create; | fStrings := TStringList.Create; | ||
fObj := TNameObject.Create(nil); | fObj := TNameObject.Create(nil); | ||
− | + | END; | |
− | + | DESTRUCTOR TBaseObject.Destroy; | |
− | + | BEGIN | |
− | // | + | // деструктор коллекции и StringList |
fColl.Free; | fColl.Free; | ||
fStrings.Free; | fStrings.Free; | ||
fObj.Free; | fObj.Free; | ||
− | + | INHERITED Destroy; | |
− | + | END; | |
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Если вы не хотите больше функций для данных классов, их определение закончено. | |
− | == | + | == Загрузка JSON == |
− | + | С помощью метода <syntaxhighlight inline lang=pascal>Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject);</syntaxhighlight> в классе [[TJSONDeStreamer]] вы можете присвоить данные в формате JSON непосредственно ''существующему'' объекту; перед тем, как вызвать этот метод, вы должны создать TJSONDeStreamer и целевой объект. | |
− | + | Следующий метод загружает данные из структуры JSON <syntaxhighlight inline lang=pascal>JSON_TESTDATA</syntaxhighlight> в объект "о" и затем выводит текущие значения свойств в консоли. | |
− | <syntaxhighlight> | + | <syntaxhighlight lang="pascal"> |
− | + | PROCEDURE DeStreamTest; | |
− | + | VAR | |
DeStreamer: TJSONDeStreamer; | DeStreamer: TJSONDeStreamer; | ||
o: TBaseObject; | o: TBaseObject; | ||
no: TNameObject; | no: TNameObject; | ||
s: String; | s: String; | ||
− | + | BEGIN | |
− | WriteLn('DeStream | + | WriteLn('тест DeStream'); |
WriteLn('======================================'); | WriteLn('======================================'); | ||
− | // DeStreamer | + | // объект DeStreamer и целевой объект |
DeStreamer := TJSONDeStreamer.Create(nil); | DeStreamer := TJSONDeStreamer.Create(nil); | ||
o := TBaseObject.Create; | o := TBaseObject.Create; | ||
− | + | TRY | |
− | // | + | // загрузка данных JSON в объект o |
DeStreamer.JSONToObject(JSON_TESTDATA, o); | DeStreamer.JSONToObject(JSON_TESTDATA, o); | ||
// ID | // ID | ||
WriteLn(o.id); | WriteLn(o.id); | ||
− | // | + | // имя объекта |
WriteLn(o.obj.name); | WriteLn(o.obj.name); | ||
− | // | + | // напечатать имена всех объектов |
for TCollectionItem(no) in o.coll do | for TCollectionItem(no) in o.coll do | ||
Writeln(no.name); | Writeln(no.name); | ||
− | // | + | // вывести все строки |
for s in o.strings do | for s in o.strings do | ||
WriteLn(s); | WriteLn(s); | ||
− | // | + | // очистка |
− | + | FINALLY | |
o.Destroy; | o.Destroy; | ||
DeStreamer.Destroy; | DeStreamer.Destroy; | ||
− | + | END; | |
− | + | END; | |
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | == Сохранение JSON == |
− | + | Для преобразования объекта в текст JSON, используется класс [[TJSONStreamer]]. Здесь используется метод <syntaxhighlight inline lang=pascal> FUNCTION ObjectToJSONString(AObject : TObject) : TJSONStringType;</syntaxhighlight>. | |
− | + | В следующей процедуре, объект создается, заполняется данными теста, а затем преобразуются в формат JSON. Порядок, в котором сохраняются свойства не могут зависеть от программиста. | |
− | + | И, наконец, текст JSON выводится на консоль. | |
− | <syntaxhighlight> | + | <syntaxhighlight lang="Pascal"> |
− | + | PROCEDURE StreamTest; | |
− | + | VAR | |
Streamer: TJSONStreamer; | Streamer: TJSONStreamer; | ||
o: TBaseObject; | o: TBaseObject; | ||
JSONString: String; | JSONString: String; | ||
− | + | 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 | |
− | // | + | // установка данных |
o.id := 123; | o.id := 123; | ||
− | o.obj.name := ' | + | o.obj.name := 'Привет, мир!'; |
− | TNameObject(o.coll.Add).name := ' | + | TNameObject(o.coll.Add).name := 'Объект 1'; |
− | TNameObject(o.coll.Add).name := ' | + | TNameObject(o.coll.Add).name := 'Объект 2'; |
− | o.strings.Add(' | + | o.strings.Add('Привет 1'); |
− | o.strings.Add(' | + | o.strings.Add('Привет 2'); |
− | Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // | + | Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // сохранение строки в JSON |
− | // JSON | + | // конвертация вывод и JSON |
JSONString := Streamer.ObjectToJSONString(o); | JSONString := Streamer.ObjectToJSONString(o); | ||
WriteLn(JSONString); | WriteLn(JSONString); | ||
− | // | + | // очистка |
− | + | FINALLY | |
o.Destroy; | o.Destroy; | ||
Streamer.Destroy; | Streamer.Destroy; | ||
− | + | END; | |
− | + | END; | |
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | == Вывод == |
− | + | С помощью представленного знания, простые и сложные структуры данных JSON могут быть загружены в ваши программы на Free Pascal. Если необходима какая-либо пред- или постобработка данных JSON, текстовые данные могут быть изначально загружены в структуру данных в формате JSON (классом [[TJSONParser]] из юнита [[jsonparser]]), а затем можно обрабатывать с помощью юнита [[fpJSON]]. | |
− | + | Опции свойства TJSONStreamer могут быть использованы для управления представлением ваших собственных структур данных в формате JSON. | |
− | == | + | == Смотрите также == |
− | * [[JSON]] | + | * [[JSON/ru|JSON]] |
− | * [[fcl-json]] | + | * [[fcl-json/ru|fcl-json]] |
* [[Streaming components]] | * [[Streaming components]] | ||
− | == | + | == Примечания & Ссылки == |
# <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> | ||
− | |||
− | |||
− | |||
− | |||
− |
Latest revision as of 17:18, 6 August 2022
│
Deutsch (de) │
English (en) │
polski (pl) │
русский (ru) │
中文(中国大陆) (zh_CN) │
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.