Sign in Join
Wiki copytemporary

fcl-json: what changed

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

OldNewLine
11# General info
22
33fcl-json is a [[JSON]] implementation.
44
55It contains units such as:
66
77- fpjson: base unit which implements TJsonData and its children, e.g. TJsonObject
88- jsonParser: implements TJsonParser, used in the From JsonViewer example below
99- jsonConf: implements TJsonConfig which is handy to read/write application data from/to files
1010- jsonScanner: json source lexical analyzer
1111
1212Note: In fpjson, accessing e.g.
1313
1414``` pascal
1515SomeJSONObject.Integers['price']
1616```
1717
1818may give a SIGSEGV/Access Violation if that integer variable does not exist. This is apparently intentional, see [1](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.
1919
2020# Streaming
2121
2222fcl-json contains the unit "fpjsonrtti" which is used to load objects (TObject instances) from or save them to JSON format.
2323
2424See [[Streaming JSON]] for a short example.
2525
2626# Examples
2727
2828## Getting Started
2929
3030``` pascal
3131uses
3232 fpjson, jsonparser;
3333
3434procedure JSONTest;
3535var
3636 jData : TJSONData;
3737 jObject : TJSONObject;
3838 jArray : TJSONArray;
3939 s : String;
4040begin
4141 // this is only a minimal sampling of what can be done with this API
4242
4343 // create from string
4444 jData := GetJSON('{"Fld1" : "Hello", "Fld2" : 42, "Colors" : ["Red", "Green", "Blue"]}');
4545
4646 // output as a flat string
4747 s := jData.AsJSON;
4848
4949 // output as nicely formatted JSON
5050 s := jData.FormatJSON;
5151
5252 // cast as TJSONObject to make access easier
5353 jObject := jData as TJSONObject;
5454
5555 // retrieve value of Fld1
5656 s := jObject.Get('Fld1');
5757
5858 // change value of Fld2
5959 jObject.Integers['Fld2'] := 123;
6060
6161 // retrieve the second color
6262 s := jData.FindPath('Colors[1]').AsString;
6363
6464 // add a new element
6565 jObject.Add('Happy', True);
6666
6767 // add a new sub-array
6868 jArray := TJSONArray.Create;
6969 jArray.Add('North');
7070 jArray.Add('South');
7171 jArray.Add('East');
7272 jArray.Add('West');
7373 jObject.Add('Directions', jArray);
7474
7575end;
7676```
7777
7878Note: it's necessary to free jData when you have finished with it. Otherwise a memory leak is created.
7979
8080## Traversing Items
8181
8282``` pascal
8383uses
8484 Classes, TypInfo, fpjson, jsonparser;
8585
8686procedure JSONItems(Info: TStrings);
8787var
8888 jData : TJSONData;
8989 jItem : TJSONData;
9090 i, j: Integer;
9191 object_name, field_name, field_value, object_type, object_items: String;
9292begin
9393 jData := GetJSON('{"A":{"field1":0, "field2": false},"B":{"field1":0, "field2": false}}');
9494
9595 for i := 0 to jData.Count - 1 do
9696 begin
9797 jItem := jData.Items[i];
9898
9999 object_type := GetEnumName(TypeInfo(TJSONtype), Ord(jItem.JSONType));
100100 object_name := TJSONObject(jData).Names[i];
101101 WriteStr(object_items, jItem.Count);
102102
103103 Info.Append('object type: ' + object_type + '|object name: ' + object_name + '|number of fields: ' + object_items);
104104
105105 for j := 0 to jItem.Count - 1 do
106106 begin
107107 field_name := TJSONObject(jItem).Names[j];
108108 field_value := jItem.FindPath(TJSONObject(jItem).Names[j]).AsString;
109109
110110 Info.Append(field_name + '|' + field_value);
111111 end;
112112 end;
113113
114114 jData.Free;
115115end;
116116```
117117
118118## Save/load form position to/from file
119119
120120``` pascal
121121uses
122122 jsonConf;
123123
124124procedure SaveFormPos(AForm: TForm; const AFilename: string);
125125var
126126 c: TJSONConfig;
127127begin
128128 c:= TJSONConfig.Create(Nil);
129129 try
130130 //try/except to handle broken json file
131131 try
132132 c.Formatted:= true;
133133 c.Filename:= AFilename;
134134 except
135135 exit;
136136 end;
137137
138138 c.SetValue('/dialog/max', AForm.WindowState=wsMaximized);
139139 if AForm.WindowState<>wsMaximized then
140140 begin
141141 c.SetValue('/dialog/posx', AForm.Left);
142142 c.SetValue('/dialog/posy', AForm.Top);
143143 c.SetValue('/dialog/sizex', AForm.Width);
144144 c.SetValue('/dialog/sizey', AForm.Height);
145145 end;
146146 finally
147147 c.Free;
148148 end;
149149end;
150150
151151procedure LoadFormPos(AForm: TForm; const AFilename: string);
152152var
153153 nLeft, nTop, nW, nH: Integer;
154154 c: TJSONConfig;
155155begin
156156 c:= TJSONConfig.Create(Nil);
157157 try
158158 //try/except to handle broken json file
159159 try
160160 c.Formatted:= true;
161161 c.Filename:= AFilename;
162162 except
163163 exit;
164164 end;
165165
166166 nLeft:= c.GetValue('/dialog/posx', AForm.Left);
167167 nTop:= c.GetValue('/dialog/posy', AForm.Top);
168168 nW:= c.GetValue('/dialog/sizex', AForm.Width);
169169 nH:= c.GetValue('/dialog/sizey', AForm.Height);
170170 AForm.SetBounds(nLeft, nTop, nW, nH);
171171
172172 if c.GetValue('/dialog/max', false) then
173173 AForm.WindowState:= wsMaximized;
174174 finally
175175 c.Free;
176176 end;
177177end;
178178```
179179
180180## Save/load TStringList
181181
182182``` pascal
183183uses
184184 jsonConf;
185185var
186186 cfg: TJSONConfig;
187187 List: TStringList;
188188 path: string;
189189begin
190190 List:= TStringList.Create;
191191 cfg:= TJSONConfig.Create(nil);
192192 try
193193 //try/except to handle broken json file
194194 try
195195 cfg.Formatted:= true;
196196 cfg.Filename:= AJsonFilename;
197197 except
198198 exit;
199199 end;
200200
201201 cfg.GetValue('/mylist', List, '');
202202 List.Add('some_value');
203203 cfg.SetValue('/mylist', List);
204204 finally
205205 cfg.Free;
206206 List.Free;
207207 end;
208208```
209209
210210## From JsonViewer
211211
212212Example usage can be found in the Lazarus jsonviewer tool (located in lazarus/tools/jsonviewer). In particular, this part of the tool shows how to use json:
213213
214214``` pascal
215215procedure TMainForm.OpenFile(Const AFileName : String);
216216var
217217 S : TFileStream;
218218 P : TJSONParser;
219219 D : TJSONData;
220220begin
221221 S:=TFileStream.Create(AFileName,fmOpenRead);
222222 try
223223 P:=TJSONParser.Create(S);
224224 try
225225 P.Strict:=FStrict;
226226 D:=P.Parse;
227227 finally
228228 P.Free;
229229 end;
230230 finally
231231 S.Free;
232232 end;
233233 FFileName:=AFileName;
234234 SetCaption;
235235 FreeAndNil(FRoot);
236236 FRoot:=D;
237237 ShowJSONDocument;
238238end;
239239
240240procedure TMainForm.ShowJSONDocument;
241241begin
242242 with TVJSON.Items do
243243 begin
244244 BeginUpdate;
245245 try
246246 TVJSON.Items.Clear;
247247 SHowJSONData(Nil,FRoot);
248248 with TVJSON do
249249 if (Items.Count>0) and Assigned(Items[0]) then
250250 begin
251251 Items[0].Expand(False);
252252 Selected:=Items[0];
253253 end;
254254 finally
255255 EndUpdate;
256256 end;
257257 end;
258258end;
259259
260260procedure TMainForm.ShowJSONData(AParent : TTreeNode; Data : TJSONData);
261261var
262262 N,N2 : TTreeNode;
263263 I : Integer;
264264 D : TJSONData;
265265 C : String;
266266 S : TStringList;
267267begin
268268 N:=Nil;
269269 if Assigned(Data) then
270270 begin
271271 case Data.JSONType of
272272 jtArray,
273273 jtObject:
274274 begin
275275 if (Data.JSONType=jtArray) then
276276 C:=SArray
277277 else
278278 C:=SObject;
279279 N:=TVJSON.Items.AddChild(AParent,Format(C,[Data.Count]));
280280 S:=TstringList.Create;
281281 try
282282 for I:=0 to Data.Count-1 do
283283 if Data.JSONtype=jtArray then
284284 S.AddObject(IntToStr(I),Data.items[i])
285285 else
286286 S.AddObject(TJSONObject(Data).Names[i],Data.items[i]);
287287 if FSortObjectMembers and (Data.JSONType=jtObject) then
288288 S.Sort;
289289 for I:=0 to S.Count-1 do
290290 begin
291291 N2:=TVJSON.Items.AddChild(N,S[i]);
292292 D:=TJSONData(S.Objects[i]);
293293 N2.ImageIndex:=ImageTypeMap[D.JSONType];
294294 N2.SelectedIndex:=ImageTypeMap[D.JSONType];
295295 ShowJSONData(N2,D);
296296 end
297297 finally
298298 S.Free;
299299 end;
300300 end;
301301 jtNull:
302302 N:=TVJSON.Items.AddChild(AParent,SNull);
303303 else
304304 N:=TVJSON.Items.AddChild(AParent,Data.AsString);
305305 end;
306306 if Assigned(N) then
307307 begin
308308 N.ImageIndex:=ImageTypeMap[Data.JSONType];
309309 N.SelectedIndex:=ImageTypeMap[Data.JSONType];
310310 N.Data:=Data;
311311 end;
312312 end;
313313end;
314314```
315315
316316## Change formatting of float numbers
317317
318318Q: My program generates and writes data to JSON file. I use FormatJSON() method to make output more readable. I'm not quite satisfied how numbers with float point look:
319319
320-`"coordinates" : [`\
321-`     5.5978631048365003E+001,`\
322-`     2.2100000000000000E+002`\
323-`]`
320+```text
321+"coordinates" : [
322+ 5.5978631048365003E+001,
323+ 2.2100000000000000E+002
324+]
325+```
324326
325327I want to see normal form:
326328
327-`"coordinates" : [`\
328-`     55.978631048365003,`\
329-`     221.0`\
330-`]`
329+```text
330+"coordinates" : [
331+ 55.978631048365003,
332+ 221.0
333+]
334+```
331335
332336A (forum members **y.ivanov**, **rvk**, **wp**):
333337
334338``` pascal
335339{$mode objfpc}{$h+}
336340uses
337341 fpjson,
338342 jsonparser,
339343 SysUtils;
340344
341345type
342346 TJSONFloat4Number = class(TJSONFloatNumber)
343347 protected
344348 function GetAsString: TJSONStringType; override;
345349 end;
346350
347351function TJSONFloat4Number.GetAsString: TJSONStringType;
348352var
349353 F: TJSONFloat;
350354 fs: TFormatSettings;
351355begin
352356 fs := DefaultFormatSettings;
353357 fs.DecimalSeparator := '.';
354358 F := GetAsFloat;
355359 Result := FormatFloat('0.0###############', F, fs); // format with your preferences
356360end;
357361
358362procedure JSONTest;
359363var
360364 jData: TJSONData;
361365begin
362366 jData := GetJSON('{"coordinates": [5.5978631048365003E+001, 2.2100000000000000E+002]}');
363367 writeln(jData.FormatJSON);
364368 jData.Free;
365369end;
366370
367371begin
368372 SetJSONInstanceType(jitNumberFloat, TJSONFloat4Number);
369373 JSONTest;
370374 Readln;
371375end.
372376```
373377
374378## See also
375379
376380- The FpcTwit example in the [[Components and Code examples]] library makes use of JSON to send/receive data.
377381- [FCL Reference](https://lazarus-ccr.sourceforge.io/fpcdoc/fcl/fpjson/index.html) for unit fpjson.
378382- [An article (PDF)](http://www.freepascal.org/~michael/articles/webdata/webdata.pdf) covering use of XML and JSON in FreePascal.
379383- [[Package List]]
380384
381385---
382386*From the Free Pascal wiki, page "fcl-json", as it stood on 2022-10-06 after a change by Alextp, 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).*

Back to history