Sign in Join
Wiki copytemporary

Streaming JSON/zh CN: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-[[JSON]] (JavaScript Object Notation)是一种基于文本的标准化数据格式。顾名思义,JSON 文档是有效的 JavaScript 代码,可以直接转换为 JavaScript 对象。但是,无论使用哪种编程语言,JSON 都可用于数据交换。
1+[[JSON]] (JavaScript Object Notation)是一种基于文本的标准化数据格式。顾名思义,JSON 文档是有效的 JavaScript 代码,可以直接转换为 JavaScript 对象。但是,无论使用哪种编程语言,JSON 都可用于数据交换。
22
3-本教程解释了如何将 JSON 数据加载到免费的 Pascal 程序中并在那里进行处理。它还解释了如何将数据从程序转换为JSON(例如将其发送到Web浏览器)。
3+本教程解释了如何将 JSON 数据加载到免费的 Pascal 程序中并在那里进行处理。它还解释了如何将数据从程序转换为JSON(例如将其发送到Web浏览器)。
44
55## General requirements
66
7-加载和存储(流式处理)对象是通过 fpjsonrtti 单元完成的。使用类单元也很有意义(有关详细信息,请参见下文)。
8-
9-因此,uses 语句应至少包含以下两个单元:
7+加载和存储(流式处理)对象是通过 fpjsonrtti 单元完成的。使用类单元也很有意义(有关详细信息,请参见下文)。
108
11-``` pascal
9+因此,uses 语句应至少包含以下两个单元:
10+```
1211uses Classes, fpjsonrtti;
1312```
1413
15-目前(2014 年 \<\> 月)Free Pascal 的流媒体系统和 JSON 之间存在一些差异:
16-
17-- JSON 是区分大小写的数据格式。因此,Free Pascal对象的属性必须以与JSON属性相同的方式编写。
18-- No properties can be defined with DefineProperties. No references to methods (event handlers) can be saved.2
19-- [[TCollection]] and [[TStrings]] can used as a replacements for arrays.
14+目前(2014 年 <> 月)Free Pascal 的流媒体系统和 JSON 之间存在一些差异:
2015
21-Demo programs are provided with Free Pascal Compiler source code in the `packages/fcl-json/examples` directory.
16+ * JSON 是区分大小写的数据格式。因此,Free Pascal对象的属性必须以与JSON属性相同的方式编写。
17+ * No properties can be defined with DefineProperties. No references to methods (event handlers) can be saved.2
18+ * [[TCollection]] and [[TStrings]] can used as a replacements for arrays.
19+ * 无法使用DefineProperties定义属性。无法保存对方法(事件处理程序)的引用。2
20+ * TCollection和TStrings可用作数组的替代品。
2221
23-This JSON structure is used in the examples which follow:
22+示例程序与Free Pascal Compiler源代码一起提供在`packages/fcl-json/examples`目录中。
2423
25-``` JavaScript
24+以下示例中使用了此JSON结构
25+```
2626{
27- "id" : 123, // an integer
28- "obj" : { "name": "Hello world!" }, // an object
29- "coll" : [ { "name": "Object 1" }, { "name": "Object 2" } ], // two objects in a TCollection
30- "strings": [ "Hello 1", "Hello 2" ] // a string list
31-}
27+ "id" : 123, // an integer
28+ "obj" : { "name": "Hello world!" }, // an object
29+ "coll" : [ { "name": "Object 1" }, { "name": "Object 2" } ], // two objects in a TCollection
30+ "strings": [ "Hello 1", "Hello 2" ] // a string list
31+ }
3232```
3333
34-It can be defined in your Free Pascal program using a constant assignment as follows:
35-
36-``` pascal
34+在您的Free Pascal程序中,可以使用常量赋值来定义它,如下所示:
35+```
3736const JSON_TESTDATA =
38-'{'+LineEnding+
39-' "id": 123,'+LineEnding+
40-' "obj": { "name": "Hello world!" },'+LineEnding+
41-' "coll": [ { "name": "Object 1" }, { "name": "Object 2" } ],'+LineEnding+
42-' "strings": [ "Hello 1", "Hello 2" ]'+LineEnding+
43-'}';
37+ '{'+LineEnding+
38+ ' "id": 123,'+LineEnding+
39+ ' "obj": { "name": "Hello world!" },'+LineEnding+
40+ ' "coll": [ { "name": "Object 1" }, { "name": "Object 2" } ],'+LineEnding+
41+ ' "strings": [ "Hello 1", "Hello 2" ]'+LineEnding+
42+ '}';
4443```
4544
4645## Data Structure
4746
48-The base class for the data is [[TPersistent]] from the Classes unit, [[Runtime Type Information (RTTI)|runtime type information (RTTI)]] is created for it and all subclasses. These are essential for streaming. Since fpjsonrtti does not integrate into the streaming system, any other class translated with the compiler switch **{\$M+}** can also be used.
49-
50-All properties to be read must be declared as a [[Property|property]] in the [[Published|published]] section of the class. As a rule, you can use read and write to refer directly to a data field (the variable). If you want, you can of course use getter and setter methods.
47+数据的基础类是来自Classes单元的[[TPersistent]],为其及所有子类创建了[[运行时类型信息(RTTI)|runtime type information (RTTI)]]。这些对于流处理是至关重要的。由于fpjsonrtti并未集成到流处理系统中,因此也可以使用编译器开关 **{$M+}** 翻译的任何其他类。
5148
52-The following class definition results from the JSON structure:
49+要读取的所有[[Property|property]] 必须在类的 [[Published|published]] 部分中声明为属性。通常,您可以直接使用read和write来引用数据字段(变量)。当然,如果您愿意,也可以使用getter和setter方法。
5350
54-``` pascal
51+以下类定义由JSON结构得出:
52+```
5553type
56- TNameObject = class(TCollectionItem) // class for the 'obj' property and TCollection
57- private
58- fName: String;
59- published
60- property name: String read fName write fName;
61- end;
62-
63- TBaseObject = class(TPersistent) // class for the entire JSON structure
64- private
65- fid: Integer;
66- fObj: TNameObject;
67- fColl: TCollection;
68- fStrings: TStrings;
69- public
70- constructor Create;
71- destructor Destroy; override;
72- published // all properties must be published
73- property id: Integer read fid write fid;
74- property obj: TNameObject read fObj write fObj;
75- property coll: TCollection read fColl;
76- property strings: TStrings read fStrings;
77- end;
54+ TNameObject = class(TCollectionItem) // class for the 'obj' property and TCollection
55+ private
56+ fName: String;
57+ published
58+ property name: String read fName write fName;
59+ end;
60+
61+ TBaseObject = class(TPersistent) // class for the entire JSON structure
62+ private
63+ fid: Integer;
64+ fObj: TNameObject;
65+ fColl: TCollection;
66+ fStrings: TStrings;
67+ public
68+ constructor Create;
69+ destructor Destroy; override;
70+ published // all properties must be published
71+ property id: Integer read fid write fid;
72+ property obj: TNameObject read fObj write fObj;
73+ property coll: TCollection read fColl;
74+ property strings: TStrings read fStrings;
75+ end;
7876```
7977
80-The `TNameObject` class was derived from [[TCollectionItem]]. This means that it can be used both for the obj property and in the collection. If this is not desired, then two different classes must be defined here.
81-
82-The TCollection and the string list must be created in the constructor of the TBaseObject class and released in the destructor.
78+`TNameObject`类是从 [[TCollectionItem]]派生的。这意味着它既可以用于obj属性,也可以用于集合中。如果这不是所期望的,那么必须在此处定义两个不同的类。
8379
84-``` pascal
80+TCollection和字符串列表必须在TBaseObject类的构造函数中创建,并在析构函数中释放。
81+```
8582constructor TBaseObject.Create;
86-begin
87- // Create Collection and StringList
88- fColl := TCollection.Create(TNameObject);
89- fStrings := TStringList.Create;
90- fObj := TNameObject.Create(nil);
91-end;
92-
93-destructor TBaseObject.Destroy;
94-begin
95- // Release Collection and StringList
96- fColl.Free;
97- fStrings.Free;
98- fObj.Free;
99- inherited Destroy;
100-end;
83+ begin
84+ // Create Collection and StringList
85+ fColl := TCollection.Create(TNameObject);
86+ fStrings := TStringList.Create;
87+ fObj := TNameObject.Create(nil);
88+ end;
89+
90+ destructor TBaseObject.Destroy;
91+ begin
92+ // Release Collection and StringList
93+ fColl.Free;
94+ fStrings.Free;
95+ fObj.Free;
96+ inherited Destroy;
97+ end;
10198```
10299
103-If you do not want any more functionality in the data classes, their definition is now complete.
100+如果您不希望在数据类中添加更多功能,那么它们的定义现在已经完成。
104101
105102## Load JSON
106103
107-With the method `Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject);` 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.
108-
109-The following method loads the data from the JSON structure `JSON_TESTDATA` in the object o and then outputs the current values ​​of the properties to the console.
104+使用[[TJSONDeStreamer]]类中的方法`Procedure JSONToObject(Const JSON : TJSONStringType; AObject : TObject);`,您可以将JSON数据直接分配给“现有”对象。在调用此方法之前,您必须创建TJSONDeStreamer和目标对象。
110105
111-``` pascal
106+以下方法从对象o中的JSON结构`JSON_TESTDATA`加载数据,然后将属性的当前值输出到控制台。
107+```
112108procedure DeStreamTest;
113-var
114- DeStreamer: TJSONDeStreamer;
115- o: TBaseObject;
116- no: TNameObject;
117- s: String;
118-begin
119- WriteLn('DeStream test');
120- WriteLn('======================================');
121-
122- // Create the DeStreamer object and target object
123- DeStreamer := TJSONDeStreamer.Create(nil);
124- o := TBaseObject.Create;
125- try
126- // Load JSON data into object o
127- DeStreamer.JSONToObject(JSON_TESTDATA, o);
128- // output ID
129- WriteLn(o.id);
130- // output object name
131- WriteLn(o.obj.name);
132- // output the names of all objects
133- for TCollectionItem(no) in o.coll do
134- Writeln(no.name);
135- // output all strings
136- for s in o.strings do
137- WriteLn(s);
138-
139- // Cleanup
140- finally
141- o.Destroy;
142- DeStreamer.Destroy;
143- end;
144-end;
109+ var
110+ DeStreamer: TJSONDeStreamer;
111+ o: TBaseObject;
112+ no: TNameObject;
113+ s: String;
114+ begin
115+ WriteLn('DeStream test');
116+ WriteLn('======================================');
117+
118+ // Create the DeStreamer object and target object
119+ DeStreamer := TJSONDeStreamer.Create(nil);
120+ o := TBaseObject.Create;
121+ try
122+ // Load JSON data into object o
123+ DeStreamer.JSONToObject(JSON_TESTDATA, o);
124+ // output ID
125+ WriteLn(o.id);
126+ // output object name
127+ WriteLn(o.obj.name);
128+ // output the names of all objects
129+ for TCollectionItem(no) in o.coll do
130+ Writeln(no.name);
131+ // output all strings
132+ for s in o.strings do
133+ WriteLn(s);
134+
135+ // Cleanup
136+ finally
137+ o.Destroy;
138+ DeStreamer.Destroy;
139+ end;
140+ end;
145141```
146142
147143## Saving JSON
148144
149-The class [[TJSONStreamer]] is used to convert an object into JSON text. Here the method `Function ObjectToJSONString(AObject : TObject) : TJSONStringType;` is used.
150-
151-In the following procedure, an object is created, filled with the test data, and then converted to JSON. The JSON text is output on the console. The order in which the properties are output cannot be specified.
145+[[TJSONStreamer]]类用于将对象转换为JSON文本。这里使用了方法`Function ObjectToJSONString(AObject : TObject) : TJSONStringType;`。
152146
153-``` pascal
147+在以下过程中,将创建一个对象,填充测试数据,然后将其转换为JSON。JSON文本将输出到控制台。无法指定属性输出的顺序。
148+```
154149procedure StreamTest;
155-var
156- Streamer: TJSONStreamer;
157- o: TBaseObject;
158- JSONString: String;
159-begin
160- WriteLn('Stream test');
161- WriteLn('======================================');
162-
163- Streamer := TJSONStreamer.Create(nil);
164- o := TBaseObject.Create;
165- try
166- // Setup data
167- o.id := 123;
168- o.obj.name := 'Hello world!';
169- TNameObject(o.coll.Add).name := 'Object 1';
170- TNameObject(o.coll.Add).name := 'Object 2';
171- o.strings.Add('Hello 1');
172- o.strings.Add('Hello 2');
173-
174- Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // Save strings as JSON array
175- // convert to JSON and output to console
176- JSONString := Streamer.ObjectToJSONString(o);
177- WriteLn(JSONString);
178-
179- // Cleanup
180- finally
181- o.Destroy;
182- Streamer.Destroy;
183- end;
184-end;
150+ var
151+ Streamer: TJSONStreamer;
152+ o: TBaseObject;
153+ JSONString: String;
154+ begin
155+ WriteLn('Stream test');
156+ WriteLn('======================================');
157+
158+ Streamer := TJSONStreamer.Create(nil);
159+ o := TBaseObject.Create;
160+ try
161+ // Setup data
162+ o.id := 123;
163+ o.obj.name := 'Hello world!';
164+ TNameObject(o.coll.Add).name := 'Object 1';
165+ TNameObject(o.coll.Add).name := 'Object 2';
166+ o.strings.Add('Hello 1');
167+ o.strings.Add('Hello 2');
168+
169+ Streamer.Options := Streamer.Options + [jsoTStringsAsArray]; // Save strings as JSON array
170+ // convert to JSON and output to console
171+ JSONString := Streamer.ObjectToJSONString(o);
172+ WriteLn(JSONString);
173+
174+ // Cleanup
175+ finally
176+ o.Destroy;
177+ Streamer.Destroy;
178+ end;
179+ end;
185180```
186181
187-## Custom properties
188-
189-Now that we can save and load to JSON, we can as well customize how the property is saved. By default a TColor (TGraphicsColor) is saved as a number, but for example we want to make it a string, so is more human readable.
190-
191-This example uses BGRABitmap library, that has a function to convert from string to color easily. The streamed control in this case is a button control from BGRAControls package.
182+既然我们能够以JSON格式进行保存和加载,我们也可以自定义属性的保存方式。默认情况下,TColor(TGraphicsColor)被保存为数字,但例如,我们希望将其保存为字符串,这样更便于人们阅读。
192183
193-This customizes how TColor is saved and loaded.
184+此示例使用了BGRABitmap库,该库具有一个可以轻松从字符串转换为颜色的函数。在这种情况下,流控制是来自BGRAControls包的按钮控件。
194185
195-Saving code:
186+这自定义了TColor的保存和加载方式。
196187
197-``` pascal
188+Saving code:
189+```
198190procedure TForm1.Button1Click(Sender: TObject);
199-var
200- Streamer: TJSONStreamer;
201- JSONString: String;
202-begin
203- Streamer := TJSONStreamer.Create(nil);
204- try
205- Streamer.OnStreamProperty:=@OnStreamProperty;
206- JSONString := Streamer.ObjectToJSONString(BCButton1.StateNormal);
207- Memo1.Lines.Text := JSONString;
208- finally
209- Streamer.Destroy;
210- end;
211-end;
191+ var
192+ Streamer: TJSONStreamer;
193+ JSONString: String;
194+ begin
195+ Streamer := TJSONStreamer.Create(nil);
196+ try
197+ Streamer.OnStreamProperty:=@OnStreamProperty;
198+ JSONString := Streamer.ObjectToJSONString(BCButton1.StateNormal);
199+ Memo1.Lines.Text := JSONString;
200+ finally
201+ Streamer.Destroy;
202+ end;
203+ end;
212204```
213-
214-``` pascal
205+```
215206procedure TForm1.OnStreamProperty(Sender: TObject; AObject: TObject;
216- Info: PPropInfo; var Res: TJSONData);
217-var
218- bgracolor: TBGRAPixel;
219-begin
220- if (Info^.PropType^.Name = 'TGraphicsColor') then
221- begin
222- bgracolor := ColorToBGRA(TColor(GetPropValue(AObject, Info, False)));
223- Res.Free;
224- Res := TJSONString.Create('rgb('+IntToStr(bgracolor.red)+','+IntToStr(bgracolor.green)+','+IntToStr(bgracolor.blue)+')');
225- end;
226-end;
207+ Info: PPropInfo; var Res: TJSONData);
208+ var
209+ bgracolor: TBGRAPixel;
210+ begin
211+ if (Info^.PropType^.Name = 'TGraphicsColor') then
212+ begin
213+ bgracolor := ColorToBGRA(TColor(GetPropValue(AObject, Info, False)));
214+ Res.Free;
215+ Res := TJSONString.Create('rgb('+IntToStr(bgracolor.red)+','+IntToStr(bgracolor.green)+','+IntToStr(bgracolor.blue)+')');
216+ end;
217+ end;
227218```
228219
229-Loading code:
230-
231-``` pascal
220+Loading code:
221+```
232222procedure TForm1.Button2Click(Sender: TObject);
233-var
234- DeStreamer: TJSONDeStreamer;
235- s: String;
236-begin
237- DeStreamer := TJSONDeStreamer.Create(nil);
238- try
239- DeStreamer.OnRestoreProperty:=@OnRestoreProperty;
240- DeStreamer.JSONToObject(Memo1.Lines.Text, BCButton1.StateNormal);
241- finally
242- DeStreamer.Destroy;
243- end;
244-end;
223+ var
224+ DeStreamer: TJSONDeStreamer;
225+ s: String;
226+ begin
227+ DeStreamer := TJSONDeStreamer.Create(nil);
228+ try
229+ DeStreamer.OnRestoreProperty:=@OnRestoreProperty;
230+ DeStreamer.JSONToObject(Memo1.Lines.Text, BCButton1.StateNormal);
231+ finally
232+ DeStreamer.Destroy;
233+ end;
234+ end;
245235```
246-
247-``` pascal
236+```
248237procedure TForm1.OnRestoreProperty(Sender: TObject; AObject: TObject;
249- Info: PPropInfo; AValue: TJSONData; var Handled: Boolean);
250-var
251- bgracolor: TBGRAPixel;
252-begin
253- Handled := False;
254- if (Info^.PropType^.Name = 'TGraphicsColor') then
255- begin
256- Handled := True;
257- bgracolor := StrToBGRA(AValue.AsString);
258- SetPropValue(AObject, Info, BGRAToColor(bgracolor));
259- end;
260-end;
238+ Info: PPropInfo; AValue: TJSONData; var Handled: Boolean);
239+ var
240+ bgracolor: TBGRAPixel;
241+ begin
242+ Handled := False;
243+ if (Info^.PropType^.Name = 'TGraphicsColor') then
244+ begin
245+ Handled := True;
246+ bgracolor := StrToBGRA(AValue.AsString);
247+ SetPropValue(AObject, Info, BGRAToColor(bgracolor));
248+ end;
249+ end;
261250```
262251
263252## Conclusion
264253
265-With the knowledge presented, simple and complex JSON data structures can be loaded into Free Pascal programs. Should any pre- or post-processing of the JSON data be necessary, the text data can be first loaded from the [[jsonparser]] unit into a JSON data structure using the [[TJSONParser]] class and then manipulated as desired with the [[fpJSON]] unit.
266-
267-The Options property of the TJSONStreamer class can be used to control how the output maps its own data structures in JSON.
254+借助所介绍的知识,简单和复杂的JSON数据结构均可加载到Free Pascal程序中。如果需要对JSON数据进行任何预处理或后处理,可以先利用[[TJSONParser]]类从[[jsonparser]]单元将文本数据加载到JSON数据结构中,然后再使用[[fpJSON]]单元按需进行处理。
268255
269256## See Also
270257
271-- [[JSON]]
272-- [[fcl-json]]
273-- [[Streaming components]]
258+ * [[JSON]]
259+ * [[fcl-json]]
260+ * [[Streaming components]]
274261
275262## Notes & References
276263
277-1. <http://lists.freepascal.org/fpc-pascal/2013-January/036254.html>
264+ 1. <http://lists.freepascal.org/fpc-pascal/2013-January/036254.html>
278265
279-2. \<div id="ref2\>http://lists.lazarus.freepascal.org/pipermail/lazarus/2011-January/058878.html
266+ 2. <http://lists.lazarus.freepascal.org/pipermail/lazarus/2011-January/058878.html>
280267
281268---
282-*From the Free Pascal wiki, page "Streaming JSON/zh CN", as it stood on 2023-05-01 after a change by Clzwf, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
269+*From the Free Pascal wiki, page "Streaming JSON/zh CN", as the Internet Archive kept it on 2025-02-17, last changed on 2024-09-14. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history