|
@@ -17,6 +17,7 @@ unit fpjson;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
|
|
{$i fcl-json.inc}
|
|
{$i fcl-json.inc}
|
|
|
|
+{$modeswitch advancedrecords}
|
|
|
|
|
|
interface
|
|
interface
|
|
|
|
|
|
@@ -121,7 +122,7 @@ Type
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TJSONData }
|
|
{ TJSONData }
|
|
-
|
|
|
|
|
|
+
|
|
TJSONData = class(TObject)
|
|
TJSONData = class(TObject)
|
|
private
|
|
private
|
|
Const
|
|
Const
|
|
@@ -131,7 +132,18 @@ Type
|
|
class procedure DetermineElementSeparators;
|
|
class procedure DetermineElementSeparators;
|
|
class function GetCompressedJSON: Boolean; {$IFNDEF PAS2JS}static;{$ENDIF}
|
|
class function GetCompressedJSON: Boolean; {$IFNDEF PAS2JS}static;{$ENDIF}
|
|
class procedure SetCompressedJSON(AValue: Boolean); {$IFNDEF PAS2JS}static;{$ENDIF}
|
|
class procedure SetCompressedJSON(AValue: Boolean); {$IFNDEF PAS2JS}static;{$ENDIF}
|
|
- protected
|
|
|
|
|
|
+
|
|
|
|
+ protected type
|
|
|
|
+ TFormatJSONContext = record
|
|
|
|
+ Options: TFormatOptions;
|
|
|
|
+ S: TJSONStringType; // .Join does not work very well for utf8string...
|
|
|
|
+ {$ifndef Pas2JS} SUsed, {$endif} NCachedIndents, IndentSize: SizeInt;
|
|
|
|
+ CachedIndents: array of TJSONStringType;
|
|
|
|
+ procedure Append(const Piece: TJSONStringType);
|
|
|
|
+ procedure AppendIndent(I: SizeInt);
|
|
|
|
+ procedure CreateCachedIndent(I: SizeInt);
|
|
|
|
+ end;
|
|
|
|
+
|
|
Class Procedure DoError(Const Msg : String);
|
|
Class Procedure DoError(Const Msg : String);
|
|
Class Procedure DoError(Const Fmt : String; const Args : Array of Const);
|
|
Class Procedure DoError(Const Fmt : String; const Args : Array of Const);
|
|
Function DoFindPath(Const APath : TJSONStringType; Out NotFound : TJSONStringType) : TJSONdata; virtual;
|
|
Function DoFindPath(Const APath : TJSONStringType; Out NotFound : TJSONStringType) : TJSONdata; virtual;
|
|
@@ -160,7 +172,7 @@ Type
|
|
procedure SetValue(const AValue: TJSONVariant); virtual; abstract;
|
|
procedure SetValue(const AValue: TJSONVariant); virtual; abstract;
|
|
function GetItem(Index : Integer): TJSONData; virtual;
|
|
function GetItem(Index : Integer): TJSONData; virtual;
|
|
procedure SetItem(Index : Integer; const AValue: TJSONData); virtual;
|
|
procedure SetItem(Index : Integer; const AValue: TJSONData); virtual;
|
|
- Function DoFormatJSON(Options : TFormatOptions; CurrentIndent, Indent : Integer) : TJSONStringType; virtual;
|
|
|
|
|
|
+ procedure DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt); virtual;
|
|
function GetCount: Integer; virtual;
|
|
function GetCount: Integer; virtual;
|
|
Public
|
|
Public
|
|
Class function JSONType: TJSONType; virtual;
|
|
Class function JSONType: TJSONType; virtual;
|
|
@@ -174,7 +186,7 @@ Type
|
|
Function FindPath(Const APath : TJSONStringType) : TJSONdata;
|
|
Function FindPath(Const APath : TJSONStringType) : TJSONdata;
|
|
Function GetPath(Const APath : TJSONStringType) : TJSONdata;
|
|
Function GetPath(Const APath : TJSONStringType) : TJSONdata;
|
|
Function Clone : TJSONData; virtual; abstract;
|
|
Function Clone : TJSONData; virtual; abstract;
|
|
- Function FormatJSON(Options : TFormatOptions = DefaultFormat; Indentsize : Integer = DefaultIndentSize) : TJSONStringType;
|
|
|
|
|
|
+ Function FormatJSON(Options : TFormatOptions = DefaultFormat; Indentsize : Integer = DefaultIndentSize) : TJSONStringType;
|
|
property Count: Integer read GetCount;
|
|
property Count: Integer read GetCount;
|
|
property Items[Index: Integer]: TJSONData read GetItem write SetItem;
|
|
property Items[Index: Integer]: TJSONData read GetItem write SetItem;
|
|
property Value: TJSONVariant read GetValue write SetValue;
|
|
property Value: TJSONVariant read GetValue write SetValue;
|
|
@@ -240,7 +252,7 @@ Type
|
|
procedure SetAsInteger(const AValue: Integer); override;
|
|
procedure SetAsInteger(const AValue: Integer); override;
|
|
procedure SetAsString(const AValue: TJSONStringType); override;
|
|
procedure SetAsString(const AValue: TJSONStringType); override;
|
|
procedure SetValue(const AValue: TJSONVariant); override;
|
|
procedure SetValue(const AValue: TJSONVariant); override;
|
|
- Function DoFormatJSON(Options : TFormatOptions; CurrentIndent, Indent : Integer) : TJSONStringType; override;
|
|
|
|
|
|
+ procedure DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt); override;
|
|
public
|
|
public
|
|
Constructor Create(AValue : TJSONFloat); reintroduce;
|
|
Constructor Create(AValue : TJSONFloat); reintroduce;
|
|
class function NumberType : TJSONNumberType; override;
|
|
class function NumberType : TJSONNumberType; override;
|
|
@@ -543,7 +555,7 @@ Type
|
|
function GetCount: Integer; override;
|
|
function GetCount: Integer; override;
|
|
function GetItem(Index : Integer): TJSONData; override;
|
|
function GetItem(Index : Integer): TJSONData; override;
|
|
procedure SetItem(Index : Integer; const AValue: TJSONData); override;
|
|
procedure SetItem(Index : Integer; const AValue: TJSONData); override;
|
|
- Function DoFormatJSON(Options : TFormatOptions; CurrentIndent, Indent : Integer) : TJSONStringType; override;
|
|
|
|
|
|
+ procedure DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt); override;
|
|
public
|
|
public
|
|
Constructor Create; overload; reintroduce;
|
|
Constructor Create; overload; reintroduce;
|
|
Constructor Create(const Elements : Array of {$IFDEF PAS2JS}jsvalue{$else}Const{$ENDIF}); overload;
|
|
Constructor Create(const Elements : Array of {$IFDEF PAS2JS}jsvalue{$else}Const{$ENDIF}); overload;
|
|
@@ -696,7 +708,7 @@ Type
|
|
function GetCount: Integer; override;
|
|
function GetCount: Integer; override;
|
|
function GetItem(Index : Integer): TJSONData; override;
|
|
function GetItem(Index : Integer): TJSONData; override;
|
|
procedure SetItem(Index : Integer; const AValue: TJSONData); override;
|
|
procedure SetItem(Index : Integer; const AValue: TJSONData); override;
|
|
- Function DoFormatJSON(Options : TFormatOptions; CurrentIndent, Indent : Integer) : TJSONStringType; override;
|
|
|
|
|
|
+ procedure DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt); override;
|
|
public
|
|
public
|
|
constructor Create; reintroduce;
|
|
constructor Create; reintroduce;
|
|
Constructor Create(const Elements : Array of {$IFDEF PAS2JS}jsvalue{$else}Const{$ENDIF}); overload;
|
|
Constructor Create(const Elements : Array of {$IFDEF PAS2JS}jsvalue{$else}Const{$ENDIF}); overload;
|
|
@@ -1128,18 +1140,18 @@ begin
|
|
if (U1<>0) then
|
|
if (U1<>0) then
|
|
begin
|
|
begin
|
|
if ((U1>=$D800) and (U1<=$DBFF)) and
|
|
if ((U1>=$D800) and (U1<=$DBFF)) and
|
|
- ((U2>=$DC00) and (U2<=$DFFF)) then
|
|
|
|
|
|
+ ((U2>=$DC00) and (U2<=$DFFF)) then
|
|
begin
|
|
begin
|
|
App:={$IFDEF FPC_HAS_CPSTRING}UTF8Encode({$ENDIF}WideChar(U1)+WideChar(U2){$IFDEF FPC_HAS_CPSTRING}){$ENDIF};
|
|
App:={$IFDEF FPC_HAS_CPSTRING}UTF8Encode({$ENDIF}WideChar(U1)+WideChar(U2){$IFDEF FPC_HAS_CPSTRING}){$ENDIF};
|
|
U2:=0;
|
|
U2:=0;
|
|
- end
|
|
|
|
|
|
+ end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
App:={$IFDEF FPC_HAS_CPSTRING}UTF8Encode({$ENDIF}WideChar(U1){$IFDEF FPC_HAS_CPSTRING}){$ENDIF};
|
|
App:={$IFDEF FPC_HAS_CPSTRING}UTF8Encode({$ENDIF}WideChar(U1){$IFDEF FPC_HAS_CPSTRING}){$ENDIF};
|
|
Result:=Result+App;
|
|
Result:=Result+App;
|
|
App:='';
|
|
App:='';
|
|
end;
|
|
end;
|
|
- end
|
|
|
|
|
|
+ end
|
|
else
|
|
else
|
|
App:='';
|
|
App:='';
|
|
U1:=U2;
|
|
U1:=U2;
|
|
@@ -1507,12 +1519,12 @@ end;
|
|
{ TJSONData }
|
|
{ TJSONData }
|
|
|
|
|
|
{$IFNDEF PAS2JS}
|
|
{$IFNDEF PAS2JS}
|
|
-function TJSONData.GetAsUnicodeString: TJSONUnicodeStringType;
|
|
|
|
|
|
+function TJSONData.GetAsUnicodeString: TJSONUnicodeStringType;
|
|
begin
|
|
begin
|
|
Result:=UTF8Decode(AsString);
|
|
Result:=UTF8Decode(AsString);
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure TJSONData.SetAsUnicodeString(const AValue: TJSONUnicodeStringType);
|
|
|
|
|
|
+procedure TJSONData.SetAsUnicodeString(const AValue: TJSONUnicodeStringType);
|
|
begin
|
|
begin
|
|
AsString:=UTF8Encode(AValue);
|
|
AsString:=UTF8Encode(AValue);
|
|
end;
|
|
end;
|
|
@@ -1605,6 +1617,44 @@ begin
|
|
TJSONObject.DetermineElementQuotes;
|
|
TJSONObject.DetermineElementQuotes;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TJSONData.TFormatJSONContext.Append(const Piece: TJSONStringType);
|
|
|
|
+{$ifndef PAS2JS}
|
|
|
|
+var
|
|
|
|
+ Start, NPiece: SizeInt;
|
|
|
|
+begin
|
|
|
|
+ Start := SUsed;
|
|
|
|
+ NPiece := Length(Piece);
|
|
|
|
+ Inc(SUsed, NPiece);
|
|
|
|
+ if SUsed > Length(S) then
|
|
|
|
+ SetLength(S, 128 + SUsed + SUsed shr 2 + SUsed shr 4);
|
|
|
|
+ Move(Pointer(Piece)^, (Pointer(S) + Start * SizeOf(S[1]))^, NPiece * SizeOf(S[1]));
|
|
|
|
+end;
|
|
|
|
+{$else}
|
|
|
|
+begin
|
|
|
|
+ S := S + Piece;
|
|
|
|
+end;
|
|
|
|
+{$endif}
|
|
|
|
+
|
|
|
|
+procedure TJSONData.TFormatJSONContext.AppendIndent(I: SizeInt);
|
|
|
|
+begin
|
|
|
|
+ if I <= 0 then exit; // Shortcut if 0.
|
|
|
|
+ if (I >= Length(CachedIndents)) or (CachedIndents[I] = '') then
|
|
|
|
+ CreateCachedIndent(I);
|
|
|
|
+ Append(CachedIndents[I]);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TJSONData.TFormatJSONContext.CreateCachedIndent(I: SizeInt);
|
|
|
|
+var
|
|
|
|
+ C: Char;
|
|
|
|
+begin
|
|
|
|
+ if I >= Length(CachedIndents) then
|
|
|
|
+ SetLength(CachedIndents, 16 + I + I shr 2 + I shr 4);
|
|
|
|
+ C := ' ';
|
|
|
|
+ if foUseTabChar in Options then
|
|
|
|
+ C := #9;
|
|
|
|
+ CachedIndents[I] := StringOfChar(C, I * IndentSize);
|
|
|
|
+end;
|
|
|
|
+
|
|
class procedure TJSONData.DoError(const Msg: String);
|
|
class procedure TJSONData.DoError(const Msg: String);
|
|
begin
|
|
begin
|
|
Raise EJSON.Create(Msg);
|
|
Raise EJSON.Create(Msg);
|
|
@@ -1672,19 +1722,26 @@ end;
|
|
|
|
|
|
function TJSONData.FormatJSON(Options: TFormatOptions; Indentsize: Integer
|
|
function TJSONData.FormatJSON(Options: TFormatOptions; Indentsize: Integer
|
|
): TJSONStringType;
|
|
): TJSONStringType;
|
|
-
|
|
|
|
|
|
+var
|
|
|
|
+ Ctx: TFormatJSONContext;
|
|
begin
|
|
begin
|
|
- Result:=DoFormatJSON(Options,0,IndentSize);
|
|
|
|
|
|
+ Ctx.Options := Options;
|
|
|
|
+{$ifndef Pas2JS}
|
|
|
|
+ Ctx.SUsed := 0;
|
|
|
|
+{$endif}
|
|
|
|
+ Ctx.NCachedIndents := 0;
|
|
|
|
+ Ctx.IndentSize := IndentSize;
|
|
|
|
+ DoFormatJSON(Ctx, 0);
|
|
|
|
+{$ifndef Pas2JS}
|
|
|
|
+ SetLength(Ctx.S, Ctx.SUsed);
|
|
|
|
+{$endif}
|
|
|
|
+ Result := Ctx.S;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TJSONData.DoFormatJSON(Options: TFormatOptions; CurrentIndent,
|
|
|
|
- Indent: Integer): TJSONStringType;
|
|
|
|
|
|
+procedure TJSONData.DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt);
|
|
|
|
|
|
begin
|
|
begin
|
|
- Result:=AsJSON;
|
|
|
|
- if Options=[] then ;
|
|
|
|
- if CurrentIndent=0 then ;
|
|
|
|
- if Indent>0 then ;
|
|
|
|
|
|
+ Ctx.Append(AsJSON);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TJSONnumber }
|
|
{ TJSONnumber }
|
|
@@ -2190,14 +2247,12 @@ begin
|
|
FValue:={$IFDEF PAS2JS}TJSONFloat(AValue){$else}AValue{$ENDIF};
|
|
FValue:={$IFDEF PAS2JS}TJSONFloat(AValue){$else}AValue{$ENDIF};
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TJSONFloatNumber.DoFormatJSON(Options: TFormatOptions; CurrentIndent, Indent: Integer): TJSONStringType;
|
|
|
|
|
|
+procedure TJSONFloatNumber.DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt);
|
|
begin
|
|
begin
|
|
- if (foFormatFloat in Options) then
|
|
|
|
- Result:=TJSONStringType(FloatToStr(FValue,JSONFormatSettings))
|
|
|
|
|
|
+ if (foFormatFloat in Ctx.Options) then
|
|
|
|
+ Ctx.Append(TJSONStringType(FloatToStr(FValue,JSONFormatSettings)))
|
|
else
|
|
else
|
|
- Result:=AsJSON;
|
|
|
|
- if CurrentIndent=0 then ;
|
|
|
|
- if Indent=0 then ;
|
|
|
|
|
|
+ Ctx.Append(AsJSON);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
@@ -2766,55 +2821,40 @@ begin
|
|
Result:=Result+']';
|
|
Result:=Result+']';
|
|
end;
|
|
end;
|
|
|
|
|
|
-Function IndentString(Options : TFormatOptions; Indent : Integer) : TJSONStringType;
|
|
|
|
-
|
|
|
|
-begin
|
|
|
|
- If (foUseTabChar in Options) then
|
|
|
|
- Result:=StringofChar(#9,Indent)
|
|
|
|
- else
|
|
|
|
- Result:=StringOfChar(' ',Indent);
|
|
|
|
-end;
|
|
|
|
-
|
|
|
|
-function TJSONArray.DoFormatJSON(Options: TFormatOptions; CurrentIndent,
|
|
|
|
- Indent: Integer): TJSONStringType;
|
|
|
|
|
|
+procedure TJSONArray.DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt);
|
|
|
|
|
|
Var
|
|
Var
|
|
I : Integer;
|
|
I : Integer;
|
|
MultiLine : Boolean;
|
|
MultiLine : Boolean;
|
|
SkipWhiteSpace : Boolean;
|
|
SkipWhiteSpace : Boolean;
|
|
- Ind : String;
|
|
|
|
LB : String;
|
|
LB : String;
|
|
-
|
|
|
|
|
|
+
|
|
begin
|
|
begin
|
|
- Result:='[';
|
|
|
|
- MultiLine:=Not (foSingleLineArray in Options);
|
|
|
|
- if foForceLF in Options then
|
|
|
|
|
|
+ Ctx.Append('[');
|
|
|
|
+ MultiLine:=Not (foSingleLineArray in Ctx.Options);
|
|
|
|
+ if foForceLF in Ctx.Options then
|
|
LB:=#10
|
|
LB:=#10
|
|
else
|
|
else
|
|
LB:=sLineBreak;
|
|
LB:=sLineBreak;
|
|
- SkipWhiteSpace:=foSkipWhiteSpace in Options;
|
|
|
|
- Ind:=IndentString(Options, CurrentIndent+Indent);
|
|
|
|
|
|
+ SkipWhiteSpace:=foSkipWhiteSpace in Ctx.Options;
|
|
if MultiLine then
|
|
if MultiLine then
|
|
- Result:=Result+LB;
|
|
|
|
|
|
+ Ctx.Append(LB);
|
|
For I:=0 to Count-1 do
|
|
For I:=0 to Count-1 do
|
|
begin
|
|
begin
|
|
if MultiLine then
|
|
if MultiLine then
|
|
- Result:=Result+Ind;
|
|
|
|
|
|
+ Ctx.AppendIndent(CurrentIndent + 1);
|
|
if Items[i]=Nil then
|
|
if Items[i]=Nil then
|
|
- Result:=Result+'null'
|
|
|
|
|
|
+ Ctx.Append('null')
|
|
else
|
|
else
|
|
- Result:=Result+Items[i].DoFormatJSON(Options,CurrentIndent+Indent,Indent);
|
|
|
|
|
|
+ Items[i].DoFormatJSON(Ctx, CurrentIndent + 1);
|
|
If (I<Count-1) then
|
|
If (I<Count-1) then
|
|
- if MultiLine then
|
|
|
|
- Result:=Result+','
|
|
|
|
- else
|
|
|
|
- Result:=Result+ElementSeps[SkipWhiteSpace];
|
|
|
|
|
|
+ Ctx.Append(ElementSeps[SkipWhiteSpace or MultiLine]);
|
|
if MultiLine then
|
|
if MultiLine then
|
|
- Result:=Result+LB
|
|
|
|
|
|
+ Ctx.Append(LB);
|
|
end;
|
|
end;
|
|
if MultiLine then
|
|
if MultiLine then
|
|
- Result:=Result+IndentString(Options, CurrentIndent);
|
|
|
|
- Result:=Result+']';
|
|
|
|
|
|
+ Ctx.AppendIndent(CurrentIndent);
|
|
|
|
+ Ctx.Append(']');
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
@@ -2991,7 +3031,7 @@ procedure TJSONArray.Iterate(Iterator: TJSONArrayIterator; Data: TObject);
|
|
Var
|
|
Var
|
|
I : Integer;
|
|
I : Integer;
|
|
Cont : Boolean;
|
|
Cont : Boolean;
|
|
-
|
|
|
|
|
|
+
|
|
begin
|
|
begin
|
|
I:=0;
|
|
I:=0;
|
|
Cont:=True;
|
|
Cont:=True;
|
|
@@ -3741,30 +3781,24 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
-function TJSONObject.DoFormatJSON(Options: TFormatOptions; CurrentIndent,
|
|
|
|
- Indent: Integer): TJSONStringType;
|
|
|
|
|
|
+procedure TJSONObject.DoFormatJSON(var Ctx: TFormatJSONContext; CurrentIndent : SizeInt);
|
|
|
|
|
|
Var
|
|
Var
|
|
i : Integer;
|
|
i : Integer;
|
|
- S : TJSONStringType;
|
|
|
|
MultiLine,UseQuotes, SkipWhiteSpace,SkipWhiteSpaceOnlyLeading : Boolean;
|
|
MultiLine,UseQuotes, SkipWhiteSpace,SkipWhiteSpaceOnlyLeading : Boolean;
|
|
- NSep,Sep,Ind : String;
|
|
|
|
- V : TJSONStringType;
|
|
|
|
|
|
+ NSep,Sep : String;
|
|
D : TJSONData;
|
|
D : TJSONData;
|
|
- LB : String;
|
|
|
|
|
|
+ LB : TJSONStringType;
|
|
|
|
|
|
begin
|
|
begin
|
|
- Result:='';
|
|
|
|
- UseQuotes:=Not (foDoNotQuoteMembers in options);
|
|
|
|
- MultiLine:=Not (foSingleLineObject in Options);
|
|
|
|
- if foForceLF in Options then
|
|
|
|
|
|
+ UseQuotes:=Not (foDoNotQuoteMembers in Ctx.Options);
|
|
|
|
+ MultiLine:=Not (foSingleLineObject in Ctx.Options);
|
|
|
|
+ if foForceLF in Ctx.Options then
|
|
LB:=#10
|
|
LB:=#10
|
|
else
|
|
else
|
|
LB:=sLineBreak;
|
|
LB:=sLineBreak;
|
|
- SkipWhiteSpace:=foSkipWhiteSpace in Options;
|
|
|
|
- SkipWhiteSpaceOnlyLeading:=foSkipWhiteSpaceOnlyLeading in Options;
|
|
|
|
- CurrentIndent:=CurrentIndent+Indent;
|
|
|
|
- Ind:=IndentString(Options, CurrentIndent);
|
|
|
|
|
|
+ SkipWhiteSpace:=foSkipWhiteSpace in Ctx.Options;
|
|
|
|
+ SkipWhiteSpaceOnlyLeading:=foSkipWhiteSpaceOnlyLeading in Ctx.Options;
|
|
If SkipWhiteSpace then
|
|
If SkipWhiteSpace then
|
|
begin
|
|
begin
|
|
if SkipWhiteSpaceOnlyLeading then
|
|
if SkipWhiteSpaceOnlyLeading then
|
|
@@ -3775,36 +3809,51 @@ begin
|
|
else
|
|
else
|
|
NSep:=' : ';
|
|
NSep:=' : ';
|
|
If MultiLine then
|
|
If MultiLine then
|
|
- Sep:=','+LB+Ind
|
|
|
|
|
|
+ begin
|
|
|
|
+ Sep:=','+LB { + indentation, appended manually }
|
|
|
|
+ end
|
|
else if SkipWhiteSpace then
|
|
else if SkipWhiteSpace then
|
|
Sep:=','
|
|
Sep:=','
|
|
else
|
|
else
|
|
Sep:=', ';
|
|
Sep:=', ';
|
|
|
|
+ If Count = 0 then
|
|
|
|
+ begin
|
|
|
|
+ Ctx.Append('{}');
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ if MultiLine then
|
|
|
|
+ begin
|
|
|
|
+ Ctx.Append('{');
|
|
|
|
+ Ctx.Append(LB);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ Ctx.Append(ObjStartSeps[SkipWhiteSpace]);
|
|
For I:=0 to Count-1 do
|
|
For I:=0 to Count-1 do
|
|
begin
|
|
begin
|
|
If (I>0) then
|
|
If (I>0) then
|
|
- Result:=Result+Sep
|
|
|
|
- else If MultiLine then
|
|
|
|
- Result:=Result+Ind;
|
|
|
|
- S:=StringToJSONString(Names[i]);
|
|
|
|
- If UseQuotes then
|
|
|
|
- S:='"'+S+'"';
|
|
|
|
|
|
+ Ctx.Append(Sep);
|
|
|
|
+ If MultiLine then
|
|
|
|
+ Ctx.AppendIndent(CurrentIndent + 1);
|
|
|
|
+ if UseQuotes then
|
|
|
|
+ Ctx.Append('"');
|
|
|
|
+ Ctx.Append(StringToJSONString(Names[i]));
|
|
|
|
+ if UseQuotes then
|
|
|
|
+ Ctx.Append('"');
|
|
|
|
+ Ctx.Append(NSep);
|
|
D:=Items[i];
|
|
D:=Items[i];
|
|
if D=Nil then
|
|
if D=Nil then
|
|
- V:='null'
|
|
|
|
|
|
+ Ctx.Append('null')
|
|
else
|
|
else
|
|
- v:=Items[I].DoFormatJSON(Options,CurrentIndent,Indent);
|
|
|
|
- Result:=Result+S+NSep+V;
|
|
|
|
|
|
+ D.DoFormatJSON(Ctx, CurrentIndent + 1);
|
|
end;
|
|
end;
|
|
- If (Result<>'') then
|
|
|
|
|
|
+ if MultiLine then
|
|
begin
|
|
begin
|
|
- if MultiLine then
|
|
|
|
- Result:='{'+LB+Result+LB+indentString(options,CurrentIndent-Indent)+'}'
|
|
|
|
- else
|
|
|
|
- Result:=ObjStartSeps[SkipWhiteSpace]+Result+ObjEndSeps[SkipWhiteSpace]
|
|
|
|
|
|
+ Ctx.Append(LB);
|
|
|
|
+ Ctx.AppendIndent(CurrentIndent);
|
|
|
|
+ Ctx.Append('}');
|
|
end
|
|
end
|
|
else
|
|
else
|
|
- Result:='{}';
|
|
|
|
|
|
+ Ctx.Append(ObjEndSeps[SkipWhiteSpace]);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TJSONObject.Iterate(Iterator: TJSONObjectIterator; Data: TObject);
|
|
procedure TJSONObject.Iterate(Iterator: TJSONObjectIterator; Data: TObject);
|