|
1 | 1 | (******************************************************************************) |
2 | 2 | (* uJSON.pas ??.??.???? *) |
3 | 3 | (* *) |
4 | | -(* Version : 0.14 *) |
| 4 | +(* Version : 0.15 *) |
5 | 5 | (* *) |
6 | 6 | (* Author : Uwe Schächterle (Corpsman) *) |
7 | 7 | (* *) |
|
41 | 41 | (* 0.13 = Erste Versuche eine Zeilennummer aus zu geben, wenn *) |
42 | 42 | (* der JSON Text falsch ist.. *) |
43 | 43 | (* 0.14 = Ignore \u tags instead of throwing an exception *) |
| 44 | +(* 0.15 = ADD IJSONAddobjInterface *) |
| 45 | +(* Parent Property *) |
| 46 | +(* Validy Checks on TJSONArray.addobj *) |
| 47 | +(* FIX: linebreak on TJSONNodeObj.ToString *) |
44 | 48 | (* *) |
45 | 49 | (******************************************************************************) |
46 | 50 | Unit uJSON; |
47 | 51 |
|
48 | 52 | {$MODE objfpc}{$H+} |
49 | 53 |
|
| 54 | +{$INTERFACES CORBA} |
| 55 | + |
50 | 56 | Interface |
51 | 57 |
|
52 | 58 | (* |
|
137 | 143 | private |
138 | 144 | fName: String; // Wird in Findpath benötigt |
139 | 145 | fobjs: Array Of TJSONObj; // Das ist damit TJSONObj das Findpath bereitstellen kann, sonst müssten das die Kindklassen alle Redundant implementieren |
| 146 | + fParent: TJSONObj; // das Eltern JSON Element, wenn es eines gibt, sonst NIL |
140 | 147 | protected |
141 | 148 | Procedure Clear; virtual; |
142 | 149 | public |
143 | 150 | Tag: PtrInt; // For the User, is not needed by the JSON Library = 0 on Create |
| 151 | + Property Parent: TJSONObj read fParent; |
144 | 152 | Constructor Create; virtual; |
145 | 153 | Destructor Destroy; override; |
146 | 154 |
|
|
150 | 158 | Function Clone: TJSONObj; virtual; // Abstract; // Das Object "Clont" sich selbst und wird als neue Instanz zurück gegeben |
151 | 159 | End; |
152 | 160 |
|
| 161 | + IJSONChildobjInterface = Interface |
| 162 | + ['{121D69AC-9738-455E-B2EA-C80C409D588F}'] // Created with Lazarus IDE, using CTRL+SHIFT+G |
| 163 | + Procedure AddObj(JSONObj: TJSONObj); |
| 164 | + Function RemoveObj(JSONObj: TJSONObj): Boolean; |
| 165 | + End; |
153 | 166 | { TJSONComment } |
154 | 167 |
|
155 | | - TJSONComment = Class(TJSONObj) // Will man einen JSON 5.0 Kommantar erzeugen der Parser wirft alle Kommentare weg |
| 168 | + TJSONComment = Class(TJSONObj) // Falls man einen JSON 5.0 Kommantar erzeugen will, der Parser wirft alle Kommentare weg |
156 | 169 | private |
157 | 170 |
|
158 | 171 | public |
|
168 | 181 |
|
169 | 182 | { TJSONArray } |
170 | 183 |
|
171 | | - TJSONArray = Class(TJSONObj) |
| 184 | + TJSONArray = Class(TJSONObj, IJSONChildobjInterface) |
172 | 185 | private |
173 | 186 | Function getObjCount: integer; |
174 | 187 | Function getObj(index: integer): TJSONObj; |
|
181 | 194 | Constructor Create; override; |
182 | 195 |
|
183 | 196 | Procedure AddObj(JSONObj: TJSONObj); |
| 197 | + Function RemoveObj(JSONObj: TJSONObj): Boolean; |
184 | 198 | Procedure Clear; override; |
185 | 199 |
|
186 | 200 | Function ToString(FrontSpace: String = ''): String; override; |
|
190 | 204 |
|
191 | 205 | { TJSONNode } |
192 | 206 |
|
193 | | - TJSONNode = Class(TJSONObj) |
| 207 | + TJSONNode = Class(TJSONObj, IJSONChildobjInterface) |
194 | 208 | private |
195 | 209 | Function getObjCount: integer; |
196 | 210 | Function getObj(index: integer): TJSONObj; |
|
201 | 215 | Constructor Create; override; |
202 | 216 |
|
203 | 217 | Procedure AddObj(JSONObj: TJSONObj); |
| 218 | + Function RemoveObj(JSONObj: TJSONObj): Boolean; |
204 | 219 | Procedure Clear; override; |
205 | 220 |
|
206 | 221 | Function ToString(FrontSpace: String = ''): String; override; |
|
366 | 381 | { TJSONTerminal } |
367 | 382 |
|
368 | 383 | Constructor TJSONTerminal.Create(aValue: String); |
| 384 | +Var |
| 385 | + i: Integer; |
369 | 386 | Begin |
370 | 387 | Inherited create; |
| 388 | + fName := aValue; |
371 | 389 | If length(aValue) > 1 Then Begin |
372 | 390 | If (avalue[1] = '"') And (avalue[length(aValue)] = '"') Then Begin |
373 | 391 | fName := copy(aValue, 2, length(aValue) - 2); |
| 392 | + End; |
| 393 | + End; |
| 394 | + fIsString := false; |
| 395 | + For i := 1 To length(fName) Do Begin |
| 396 | + // TODO: Das ist eigentlich falsch, weil es einen String wie 1.1.1 auch als gültige Zahl erkennen würde .. |
| 397 | + If Not (fName[i] In ['0'..'9', DefaultFormatSettings.DecimalSeparator]) Then Begin |
374 | 398 | fIsString := true; |
375 | | - End |
376 | | - Else Begin |
377 | | - fName := aValue; // Eigentlich müsste hier ne AV kommen |
378 | | - fIsString := false; |
| 399 | + break; |
379 | 400 | End; |
380 | | - End |
381 | | - Else Begin |
382 | | - fName := aValue; // Eigentlich müsste hier ne AV kommen |
383 | | - fIsString := false; |
384 | 401 | End; |
385 | 402 | End; |
386 | 403 |
|
|
419 | 436 | Tag := 0; |
420 | 437 | fName := ''; |
421 | 438 | fobjs := Nil; |
| 439 | + fParent := Nil; |
422 | 440 | End; |
423 | 441 |
|
424 | 442 | Destructor TJSONObj.Destroy; |
|
535 | 553 | setlength(result.fobjs, length(Self.fobjs)); |
536 | 554 | For i := 0 To high(fobjs) Do Begin |
537 | 555 | result.fobjs[i] := Self.fobjs[i].Clone; |
| 556 | + result.fobjs[i].fParent := result; |
538 | 557 | End; |
539 | 558 | End; |
540 | 559 |
|
541 | 560 | Procedure TJSONArray.AddObj(JSONObj: TJSONObj); |
542 | 561 | Begin |
543 | | - setlength(fobjs, High(fobjs) + 2); |
544 | | - fobjs[High(fobjs)] := JSONObj; |
| 562 | + If (JSONObj Is TJSONTerminal) Or |
| 563 | + (JSONObj Is TJSONNode) Then Begin |
| 564 | + setlength(fobjs, High(fobjs) + 2); |
| 565 | + fobjs[High(fobjs)] := JSONObj; |
| 566 | + JSONObj.fParent := self; |
| 567 | + End |
| 568 | + Else Begin |
| 569 | + Raise exception.create('Error: ' + JSONObj.ClassName + ' not allowed as element for ' + ClassName); |
| 570 | + End; |
| 571 | +End; |
| 572 | + |
| 573 | +Function TJSONArray.RemoveObj(JSONObj: TJSONObj): Boolean; |
| 574 | +Var |
| 575 | + i, j: Integer; |
| 576 | +Begin |
| 577 | + result := false; |
| 578 | + For i := 0 To high(fobjs) Do Begin |
| 579 | + If fobjs[i] = JSONObj Then Begin |
| 580 | + result := true; |
| 581 | + fobjs[i].Free; |
| 582 | + For j := i To high(fobjs) - 1 Do Begin |
| 583 | + fobjs[j] := fobjs[j + 1]; |
| 584 | + End; |
| 585 | + setlength(fobjs, high(fobjs)); |
| 586 | + exit; |
| 587 | + End; |
| 588 | + End; |
545 | 589 | End; |
546 | 590 |
|
547 | 591 | Procedure TJSONArray.Clear; |
|
595 | 639 | setlength(result.fobjs, length(Self.fobjs)); |
596 | 640 | For i := 0 To high(fobjs) Do Begin |
597 | 641 | result.fobjs[i] := Self.fobjs[i].Clone; |
| 642 | + result.fobjs[i].fParent := result; |
598 | 643 | End; |
599 | 644 | End; |
600 | 645 |
|
601 | 646 | Procedure TJSONNode.AddObj(JSONObj: TJSONObj); |
602 | 647 | Begin |
| 648 | + // TODO: darf hier wirklich alles hinzugefügt werden ? |
603 | 649 | setlength(fobjs, High(fobjs) + 2); |
604 | 650 | fobjs[High(fobjs)] := JSONObj; |
| 651 | + JSONObj.fParent := self; |
| 652 | +End; |
| 653 | + |
| 654 | +Function TJSONNode.RemoveObj(JSONObj: TJSONObj): Boolean; |
| 655 | +Var |
| 656 | + i, j: Integer; |
| 657 | +Begin |
| 658 | + result := false; |
| 659 | + For i := 0 To high(fobjs) Do Begin |
| 660 | + If fobjs[i] = JSONObj Then Begin |
| 661 | + result := true; |
| 662 | + fobjs[i].Free; |
| 663 | + For j := i To high(fobjs) - 1 Do Begin |
| 664 | + fobjs[j] := fobjs[j + 1]; |
| 665 | + End; |
| 666 | + setlength(fobjs, high(fobjs)); |
| 667 | + exit; |
| 668 | + End; |
| 669 | + End; |
605 | 670 | End; |
606 | 671 |
|
607 | 672 | Procedure TJSONNode.Clear; |
|
917 | 982 | Inherited Create; |
918 | 983 | fName := aName; |
919 | 984 | fvalue := aValue; |
| 985 | + fvalue.fParent := self; |
920 | 986 | End; |
921 | 987 |
|
922 | 988 | Function TJSONNodeObj.ToString(FrontSpace: String): String; |
| 989 | +Var |
| 990 | + maybeLE: String; |
923 | 991 | Begin |
924 | 992 | If assigned(fvalue) Then Begin |
925 | | - result := FrontSpace + StringToJsonString(fName) + ':' + fvalue.ToString(FrontSpace); |
| 993 | + maybeLE := ''; |
| 994 | + If fvalue Is TJSONNode Then maybeLE := LineEnding; |
| 995 | + result := FrontSpace + StringToJsonString(fName) + ':' + maybeLE + fvalue.ToString(FrontSpace); |
926 | 996 | End |
927 | 997 | Else Begin |
928 | 998 | result := FrontSpace + StringToJsonString(fName) + ':""'; |
|
0 commit comments