Updated JSON Parser

This commit is contained in:
Daniele Teti 2020-06-23 23:43:08 +02:00
parent a6ffb35b6f
commit a8ac6a7206

View File

@ -137,6 +137,8 @@ uses
SysUtils, Classes; SysUtils, Classes;
{$ENDIF HAS_UNIT_SCOPE} {$ENDIF HAS_UNIT_SCOPE}
{$HPPEMIT '#pragma link "Jsondataobjects"'}
type type
TJsonBaseObject = class; TJsonBaseObject = class;
TJsonObject = class; TJsonObject = class;
@ -367,7 +369,11 @@ type
function GetObjectUtcDateTime(const Name: string): TDateTime; inline; function GetObjectUtcDateTime(const Name: string): TDateTime; inline;
function GetObjectBool(const Name: string): Boolean; inline; function GetObjectBool(const Name: string): Boolean; inline;
function GetArray(const Name: string): TJsonArray; inline; function GetArray(const Name: string): TJsonArray; inline;
{$IFDEF BCB}
function GetObj(const Name: string): TJsonDataValueHelper; inline; // work around C++Builder Windows.h::GetObject macro
{$ELSE}
function GetObject(const Name: string): TJsonDataValueHelper; inline; function GetObject(const Name: string): TJsonDataValueHelper; inline;
{$ENDIF BCB}
function GetObjectVariant(const Name: string): Variant; inline; function GetObjectVariant(const Name: string): Variant; inline;
procedure SetObjectString(const Name, Value: string); inline; procedure SetObjectString(const Name, Value: string); inline;
procedure SetObjectInt(const Name: string; const Value: Integer); inline; procedure SetObjectInt(const Name: string; const Value: Integer); inline;
@ -443,7 +449,7 @@ type
// Used to auto create arrays // Used to auto create arrays
property A[const Name: string]: TJsonArray read GetArray write SetArray; property A[const Name: string]: TJsonArray read GetArray write SetArray;
// Used to auto create objects and as default property where no Implicit operator matches // Used to auto create objects and as default property where no Implicit operator matches
property O[const Name: string]: TJsonDataValueHelper read GetObject write SetObject; default; property O[const Name: string]: TJsonDataValueHelper read {$IFDEF BCB}GetObj{$ELSE}GetObject{$ENDIF} write SetObject; default;
property V[const Name: string]: Variant read GetObjectVariant write SetObjectVariant; property V[const Name: string]: Variant read GetObjectVariant write SetObjectVariant;
property Path[const Name: string]: TJsonDataValueHelper read GetObjectPath write SetObjectPath; property Path[const Name: string]: TJsonDataValueHelper read GetObjectPath write SetObjectPath;
@ -543,7 +549,7 @@ type
// ToString() returns a compact JSON string // ToString() returns a compact JSON string
function ToString: string; override; function ToString: string; override;
function Clone: TJsonBaseObject; virtual; abstract; function Clone: TJsonBaseObject;
class function JSONToDateTime(const Value: string; ConvertToLocalTime: Boolean = True): TDateTime; static; class function JSONToDateTime(const Value: string; ConvertToLocalTime: Boolean = True): TDateTime; static;
class function DateTimeToJSON(const Value: TDateTime; UseUtcTime: Boolean): string; static; class function DateTimeToJSON(const Value: TDateTime; UseUtcTime: Boolean): string; static;
@ -580,7 +586,11 @@ type
function GetUtcDateTime(Index: Integer): TDateTime; inline; function GetUtcDateTime(Index: Integer): TDateTime; inline;
function GetBool(Index: Integer): Boolean; inline; function GetBool(Index: Integer): Boolean; inline;
function GetArray(Index: Integer): TJsonArray; inline; function GetArray(Index: Integer): TJsonArray; inline;
{$IFDEF BCB}
function GetObj(Index: Integer): TJsonObject; inline;
{$ELSE}
function GetObject(Index: Integer): TJsonObject; inline; function GetObject(Index: Integer): TJsonObject; inline;
{$ENDIF BCB}
function GetVariant(Index: Integer): Variant; inline; function GetVariant(Index: Integer): Variant; inline;
procedure SetString(Index: Integer; const Value: string); inline; procedure SetString(Index: Integer; const Value: string); inline;
@ -620,7 +630,7 @@ type
function ExtractArray(Index: Integer): TJsonArray; function ExtractArray(Index: Integer): TJsonArray;
function ExtractObject(Index: Integer): TJsonObject; function ExtractObject(Index: Integer): TJsonObject;
procedure Assign(ASource: TJsonArray); procedure Assign(ASource: TJsonArray);
function Clone: TJsonBaseObject; override; function Clone: TJsonArray;
procedure Add(const AValue: string); overload; procedure Add(const AValue: string); overload;
procedure Add(const AValue: Integer); overload; procedure Add(const AValue: Integer); overload;
@ -668,7 +678,7 @@ type
property DUtc[Index: Integer]: TDateTime read GetUtcDateTime write SetUtcDateTime; property DUtc[Index: Integer]: TDateTime read GetUtcDateTime write SetUtcDateTime;
property B[Index: Integer]: Boolean read GetBool write SetBool; property B[Index: Integer]: Boolean read GetBool write SetBool;
property A[Index: Integer]: TJsonArray read GetArray write SetArray; property A[Index: Integer]: TJsonArray read GetArray write SetArray;
property O[Index: Integer]: TJsonObject read GetObject write SetObject; property O[Index: Integer]: TJsonObject read {$IFDEF BCB}GetObj{$ELSE}GetObject{$ENDIF} write SetObject;
property V[Index: Integer]: Variant read GetVariant write SetVariant; property V[Index: Integer]: Variant read GetVariant write SetVariant;
property Items[Index: Integer]: PJsonDataValue read GetItem; property Items[Index: Integer]: PJsonDataValue read GetItem;
@ -719,7 +729,11 @@ type
function GetFloat(const Name: string): Double; function GetFloat(const Name: string): Double;
function GetDateTime(const Name: string): TDateTime; function GetDateTime(const Name: string): TDateTime;
function GetUtcDateTime(const Name: string): TDateTime; function GetUtcDateTime(const Name: string): TDateTime;
{$IFDEF BCB}
function GetObj(const Name: string): TJsonObject;
{$ELSE}
function GetObject(const Name: string): TJsonObject; function GetObject(const Name: string): TJsonObject;
{$ENDIF BCB}
function GetArray(const Name: string): TJsonArray; function GetArray(const Name: string): TJsonArray;
procedure SetString(const Name, Value: string); procedure SetString(const Name, Value: string);
procedure SetBool(const Name: string; const Value: Boolean); procedure SetBool(const Name: string; const Value: Boolean);
@ -769,7 +783,7 @@ type
public public
destructor Destroy; override; destructor Destroy; override;
procedure Assign(ASource: TJsonObject); procedure Assign(ASource: TJsonObject);
function Clone: TJsonBaseObject; override; function Clone: TJsonObject;
// ToSimpleObject() maps the JSON object properties to the Delphi object by using the object's // ToSimpleObject() maps the JSON object properties to the Delphi object by using the object's
// TypeInfo. // TypeInfo.
@ -805,7 +819,7 @@ type
property DUtc[const Name: string]: TDateTime read GetUtcDateTime write SetUtcDateTime; // returns 0 if property doesn't exist, auto type-cast except for array/object property DUtc[const Name: string]: TDateTime read GetUtcDateTime write SetUtcDateTime; // returns 0 if property doesn't exist, auto type-cast except for array/object
property B[const Name: string]: Boolean read GetBool write SetBool; // returns false if property doesn't exist, auto type-cast with "<>'true'" and "<>0" except for array/object property B[const Name: string]: Boolean read GetBool write SetBool; // returns false if property doesn't exist, auto type-cast with "<>'true'" and "<>0" except for array/object
property A[const Name: string]: TJsonArray read GetArray write SetArray; // auto creates array on first access property A[const Name: string]: TJsonArray read GetArray write SetArray; // auto creates array on first access
property O[const Name: string]: TJsonObject read GetObject write SetObject; // auto creates object on first access property O[const Name: string]: TJsonObject read {$IFDEF BCB}GetObj{$ELSE}GetObject{$ENDIF} write SetObject; // auto creates object on first access
property Path[const NamePath: string]: TJsonDataValueHelper read GetPath write SetPath; property Path[const NamePath: string]: TJsonDataValueHelper read GetPath write SetPath;
@ -1139,7 +1153,7 @@ begin
if VirtualQuery(PByte(MainInstance + $1000), MemInfo, SizeOf(MemInfo)) = SizeOf(MemInfo) then if VirtualQuery(PByte(MainInstance + $1000), MemInfo, SizeOf(MemInfo)) = SizeOf(MemInfo) then
begin begin
JsonMemInfoMainBlockStart := MemInfo.AllocationBase; JsonMemInfoMainBlockStart := MemInfo.AllocationBase;
JsonMemInfoMainBlockEnd := JsonMemInfoBlockStart + MemInfo.RegionSize; JsonMemInfoMainBlockEnd := JsonMemInfoMainBlockStart + MemInfo.RegionSize;
end; end;
end; end;
end; end;
@ -1439,6 +1453,14 @@ begin
[Year, Month, Day, Hour, Minute, Second, Milliseconds]); [Year, Month, Day, Hour, Minute, Second, Milliseconds]);
end; end;
function TJsonBaseObject.Clone: TJsonBaseObject;
begin
if Self is TJsonArray then
Result := TJsonArray(Self).Clone
else
Result := TJsonObject(Self).Clone;
end;
class function TJsonBaseObject.DateTimeToJSON(const Value: TDateTime; UseUtcTime: Boolean): string; class function TJsonBaseObject.DateTimeToJSON(const Value: TDateTime; UseUtcTime: Boolean): string;
{$IFDEF MSWINDOWS} {$IFDEF MSWINDOWS}
var var
@ -1574,7 +1596,7 @@ begin
P := ParseDateTimePart(P + 1, MSec, 3); P := ParseDateTimePart(P + 1, MSec, 3);
end; end;
Result := Result + EncodeTime(Hour, Min, Sec, MSec); Result := Result + EncodeTime(Hour, Min, Sec, MSec);
if P^ <> 'Z' then if (P^ <> 'Z') and (P^ <> #0) then
begin begin
if (P^ = '+') or (P^ = '-') then if (P^ = '+') or (P^ = '-') then
begin begin
@ -3777,6 +3799,16 @@ begin
Result := FItems[Index].BoolValue; Result := FItems[Index].BoolValue;
end; end;
{$IFDEF BCB}
function TJsonArray.GetObj(Index: Integer): TJsonObject;
begin
{$IFDEF CHECK_ARRAY_INDEX}
if Cardinal(Index) >= Cardinal(FCount) then
RaiseListError(Index);
{$ENDIF CHECK_ARRAY_INDEX}
Result := FItems[Index].ObjectValue;
end;
{$ELSE}
function TJsonArray.GetObject(Index: Integer): TJsonObject; function TJsonArray.GetObject(Index: Integer): TJsonObject;
begin begin
{$IFDEF CHECK_ARRAY_INDEX} {$IFDEF CHECK_ARRAY_INDEX}
@ -3785,6 +3817,7 @@ begin
{$ENDIF CHECK_ARRAY_INDEX} {$ENDIF CHECK_ARRAY_INDEX}
Result := FItems[Index].ObjectValue; Result := FItems[Index].ObjectValue;
end; end;
{$ENDIF BCB}
function TJsonArray.GetVariant(Index: Integer): Variant; function TJsonArray.GetVariant(Index: Integer): Variant;
begin begin
@ -4298,7 +4331,7 @@ begin
end; end;
end; end;
function TJsonArray.Clone: TJsonBaseObject; function TJsonArray.Clone: TJsonArray;
begin begin
Result := TJsonArray.Create; Result := TJsonArray.Create;
try try
@ -4613,6 +4646,23 @@ begin
Result := 0; Result := 0;
end; end;
{$IFDEF BCB}
function TJsonObject.GetObj(const Name: string): TJsonObject;
var
Item: PJsonDataValue;
begin
if FindItem(Name, Item) then
Result := Item.ObjectValue
else
begin
Result := TJsonObject.Create;
AddItem(Name).ObjectValue := Result;
{$IFDEF USE_LAST_NAME_STRING_LITERAL_CACHE}
UpdateLastValueItem(Name, Item);
{$ENDIF USE_LAST_NAME_STRING_LITERAL_CACHE}
end;
end;
{$ELSE}
function TJsonObject.GetObject(const Name: string): TJsonObject; function TJsonObject.GetObject(const Name: string): TJsonObject;
var var
Item: PJsonDataValue; Item: PJsonDataValue;
@ -4628,6 +4678,7 @@ begin
{$ENDIF USE_LAST_NAME_STRING_LITERAL_CACHE} {$ENDIF USE_LAST_NAME_STRING_LITERAL_CACHE}
end; end;
end; end;
{$ENDIF BCB}
function TJsonObject.GetString(const Name: string): string; function TJsonObject.GetString(const Name: string): string;
var var
@ -5193,7 +5244,7 @@ begin
end; end;
end; end;
function TJsonObject.Clone: TJsonBaseObject; function TJsonObject.Clone: TJsonObject;
begin begin
Result := TJsonObject.Create; Result := TJsonObject.Create;
try try
@ -7774,10 +7825,17 @@ begin
Result := ObjectValue.A[Name]; Result := ObjectValue.A[Name];
end; end;
{$IFDEF BCB}
function TJsonDataValueHelper.GetObj(const Name: string): TJsonDataValueHelper;
begin
Result := ObjectValue.Values[Name];
end;
{$ELSE}
function TJsonDataValueHelper.GetObject(const Name: string): TJsonDataValueHelper; function TJsonDataValueHelper.GetObject(const Name: string): TJsonDataValueHelper;
begin begin
Result := ObjectValue.Values[Name]; Result := ObjectValue.Values[Name];
end; end;
{$ENDIF BCB}
function TJsonDataValueHelper.GetObjectVariant(const Name: string): Variant; function TJsonDataValueHelper.GetObjectVariant(const Name: string): Variant;
begin begin
@ -8260,4 +8318,3 @@ initialization
JSONFormatSettings.DecimalSeparator := '.'; JSONFormatSettings.DecimalSeparator := '.';
end. end.