|
@@ -7,7 +7,7 @@
|
|
Author : Kike Pérez
|
|
Author : Kike Pérez
|
|
Version : 1.2
|
|
Version : 1.2
|
|
Created : 21/05/2018
|
|
Created : 21/05/2018
|
|
- Modified : 30/06/2018
|
|
|
|
|
|
+ Modified : 08/07/2018
|
|
|
|
|
|
This file is part of QuickLib: https://github.com/exilon/QuickLib
|
|
This file is part of QuickLib: https://github.com/exilon/QuickLib
|
|
|
|
|
|
@@ -36,19 +36,21 @@ interface
|
|
uses
|
|
uses
|
|
Classes,
|
|
Classes,
|
|
SysUtils,
|
|
SysUtils,
|
|
|
|
+ Rtti,
|
|
|
|
+ TypInfo,
|
|
{$IFDEF FPC}
|
|
{$IFDEF FPC}
|
|
- Rtti,
|
|
|
|
rttiutils,
|
|
rttiutils,
|
|
- jsonreader,
|
|
|
|
- fpjsonrtti,
|
|
|
|
fpjson,
|
|
fpjson,
|
|
|
|
+ jsonparser,
|
|
|
|
+ strUtils,
|
|
|
|
+ //jsonreader,
|
|
|
|
+ //fpjsonrtti,
|
|
|
|
+ Quick.Json.fpc.Compatibility,
|
|
{$ELSE}
|
|
{$ELSE}
|
|
{$IFDEF DELPHIXE7_UP}
|
|
{$IFDEF DELPHIXE7_UP}
|
|
- Rtti,
|
|
|
|
System.Json,
|
|
System.Json,
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
- TypInfo,
|
|
|
|
DateUtils,
|
|
DateUtils,
|
|
Quick.Commons;
|
|
Quick.Commons;
|
|
|
|
|
|
@@ -57,9 +59,7 @@ type
|
|
EJsonSerializeError = class(Exception);
|
|
EJsonSerializeError = class(Exception);
|
|
EJsonDeserializeError = class(Exception);
|
|
EJsonDeserializeError = class(Exception);
|
|
|
|
|
|
- {$IFDEF FPC}
|
|
|
|
- TJsonPair = TJsonData;
|
|
|
|
- {$ELSE}
|
|
|
|
|
|
+ {$IFNDEF FPC}
|
|
TNotSerializableProperty = class(TCustomAttribute);
|
|
TNotSerializableProperty = class(TCustomAttribute);
|
|
|
|
|
|
TCommentProperty = class(TCustomAttribute)
|
|
TCommentProperty = class(TCustomAttribute)
|
|
@@ -88,23 +88,46 @@ type
|
|
|
|
|
|
TSerializeLevel = (slPublicProperty, slPublishedProperty);
|
|
TSerializeLevel = (slPublicProperty, slPublishedProperty);
|
|
|
|
|
|
|
|
+ PValue = ^TValue;
|
|
|
|
|
|
TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
|
|
TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
|
|
strict private
|
|
strict private
|
|
fSerializeLevel : TSerializeLevel;
|
|
fSerializeLevel : TSerializeLevel;
|
|
- function GetValue(aAddr: Pointer; aType: TRTTIType): TValue;
|
|
|
|
|
|
+ function GetValue(aAddr: Pointer; aType: TRTTIType): TValue; overload;
|
|
|
|
+ function GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue; overload;
|
|
function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
|
|
function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
|
|
function IsGenericList(aObject : TObject) : Boolean;
|
|
function IsGenericList(aObject : TObject) : Boolean;
|
|
|
|
+ function GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
|
|
|
|
+ procedure SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue); overload;
|
|
|
|
+ procedure SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue); overload;
|
|
|
|
+ {$IFDEF FPC}
|
|
|
|
+ function FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
|
|
|
|
+ function GetPropType(aPropInfo: PPropInfo): PTypeInfo;
|
|
|
|
+ procedure LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
|
|
|
|
+ {$ENDIF}
|
|
{$IFNDEF FPC}
|
|
{$IFNDEF FPC}
|
|
function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
|
|
function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
|
|
function DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
|
|
function DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
|
|
|
|
+ {$ELSE}
|
|
|
|
+ procedure DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
|
|
function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
|
|
function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
|
|
function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
|
|
|
|
+ {$IFNDEF FPC}
|
|
function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
|
|
function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
|
|
|
|
+ {$ENDIF}
|
|
function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
|
|
function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
|
|
|
|
+ {$IFNDEF FPC}
|
|
function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
|
|
function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
|
|
|
|
+ {$ELSE}
|
|
|
|
+ function DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ {$IFNDEF FPC}
|
|
function Serialize(const aName : string; aValue : TValue) : TJSONPair; overload;
|
|
function Serialize(const aName : string; aValue : TValue) : TJSONPair; overload;
|
|
|
|
+ {$ELSE}
|
|
|
|
+ function Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
|
|
|
|
+ function Serialize(const aName : string; aValue : TValue) : TJSONPair;
|
|
|
|
+ {$ENDIF}
|
|
function Serialize(aObject : TObject) : TJSONObject; overload;
|
|
function Serialize(aObject : TObject) : TJSONObject; overload;
|
|
public
|
|
public
|
|
constructor Create(aSerializeLevel : TSerializeLevel);
|
|
constructor Create(aSerializeLevel : TSerializeLevel);
|
|
@@ -122,7 +145,7 @@ resourcestring
|
|
|
|
|
|
implementation
|
|
implementation
|
|
|
|
|
|
-{ TqlJsonSerializer }
|
|
|
|
|
|
+{ TJsonSerializer }
|
|
|
|
|
|
{$IFNDEF FPC}
|
|
{$IFNDEF FPC}
|
|
function TJsonSerializer.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
|
|
function TJsonSerializer.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
|
|
@@ -189,6 +212,68 @@ begin
|
|
DynArrayClear(pArr,aTypeInfo);
|
|
DynArrayClear(pArr,aTypeInfo);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+{$ELSE}
|
|
|
|
+procedure TJsonSerializer.DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
|
|
|
|
+var
|
|
|
|
+ rType: PTypeInfo;
|
|
|
|
+ len: NativeInt;
|
|
|
|
+ pArr: Pointer;
|
|
|
|
+ rItemValue: TValue;
|
|
|
|
+ i: Integer;
|
|
|
|
+ objClass: TClass;
|
|
|
|
+ propObj : TObject;
|
|
|
|
+ rValue : TValue;
|
|
|
|
+begin
|
|
|
|
+ if GetTypeData(aTypeInfo).ElType2 = nil then Exit;
|
|
|
|
+ len := aJsonArray.Count;
|
|
|
|
+ rType := GetTypeData(aTypeInfo).ElType2;
|
|
|
|
+ pArr := nil;
|
|
|
|
+ DynArraySetLength(pArr,aTypeInfo, 1, @len);
|
|
|
|
+ try
|
|
|
|
+ TValue.Make(@pArr,aTypeInfo, rValue);
|
|
|
|
+ for i := 0 to aJsonArray.Count - 1 do
|
|
|
|
+ begin
|
|
|
|
+ rItemValue := nil;
|
|
|
|
+ case rType.Kind of
|
|
|
|
+ tkClass :
|
|
|
|
+ begin
|
|
|
|
+ if aJsonArray.Items[i] is TJSONObject then
|
|
|
|
+ begin
|
|
|
|
+ propObj := GetValue(PPByte(rValue.GetReferenceToRawData)^ +GetTypeData(aTypeInfo).elSize * i, GetTypeData(aTypeInfo).ElType2).AsObject;
|
|
|
|
+ if propObj = nil then
|
|
|
|
+ begin
|
|
|
|
+ objClass := GetTypeData(aTypeInfo).ClassType;
|
|
|
|
+ rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ tkRecord :
|
|
|
|
+ begin
|
|
|
|
+ {json := TJSONObject(aJsonArray.Items[i]);
|
|
|
|
+ rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
|
|
|
|
+ rDynArray.ElementType),aObject,json); }
|
|
|
|
+ end;
|
|
|
|
+ tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
|
|
|
|
+ begin
|
|
|
|
+ //skip these properties
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ rItemValue := DeserializeType(aObject,GetTypeData(aTypeInfo).ElType2.Kind,aPropertyName,aJsonArray.Items[i].Value);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ if not rItemValue.IsEmpty then rValue.SetArrayElement(i,rItemValue);
|
|
|
|
+ end;
|
|
|
|
+ //aProperty.SetValue(aObject,rValue);
|
|
|
|
+ SetDynArrayProp(aObject,GetPropInfo(aObject,aPropertyName),pArr);
|
|
|
|
+ finally
|
|
|
|
+ DynArrayClear(pArr,aTypeInfo);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
|
|
{$IFNDEF FPC}
|
|
{$IFNDEF FPC}
|
|
@@ -244,7 +329,7 @@ begin
|
|
end;
|
|
end;
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.JsonString.ToString);
|
|
|
|
|
|
+ rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.toJson);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
|
|
if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
|
|
@@ -260,11 +345,7 @@ function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TO
|
|
var
|
|
var
|
|
json: TJSONObject;
|
|
json: TJSONObject;
|
|
begin
|
|
begin
|
|
- {$IFNDEF FPC}
|
|
|
|
- json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
|
|
|
|
- {$ELSE}
|
|
|
|
- json := GetJSON(aJson) as TJsonObject;
|
|
|
|
- {$ENDIF}
|
|
|
|
|
|
+ json := TJsonObject(TJSONObject.ParseJSONValue(aJson,True));
|
|
try
|
|
try
|
|
Result := DeserializeObject(aObject,json);
|
|
Result := DeserializeObject(aObject,json);
|
|
finally
|
|
finally
|
|
@@ -276,11 +357,7 @@ function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObje
|
|
var
|
|
var
|
|
json: TJSONObject;
|
|
json: TJSONObject;
|
|
begin
|
|
begin
|
|
- {$IFNDEF FPC}
|
|
|
|
- json := TJSONObject.ParseJSONValue(aJson) as TJSONObject;
|
|
|
|
- {$ELSE}
|
|
|
|
- json := GetJSON(aJson) as TJsonObject;
|
|
|
|
- {$ENDIF}
|
|
|
|
|
|
+ json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
|
|
try
|
|
try
|
|
Result := DeserializeClass(aType,json);
|
|
Result := DeserializeClass(aType,json);
|
|
finally
|
|
finally
|
|
@@ -294,11 +371,7 @@ var
|
|
begin
|
|
begin
|
|
json := Serialize(aObject);
|
|
json := Serialize(aObject);
|
|
try
|
|
try
|
|
- {$IFNDEF FPC}
|
|
|
|
Result := json.ToJSON;
|
|
Result := json.ToJSON;
|
|
- {$ELSE}
|
|
|
|
- Result := json.AsJson;
|
|
|
|
- {$ENDIF}
|
|
|
|
finally
|
|
finally
|
|
json.Free;
|
|
json.Free;
|
|
end;
|
|
end;
|
|
@@ -331,7 +404,9 @@ var
|
|
ctx: TRttiContext;
|
|
ctx: TRttiContext;
|
|
rType: TRttiType;
|
|
rType: TRttiType;
|
|
rProp: TRttiProperty;
|
|
rProp: TRttiProperty;
|
|
|
|
+ {$IFNDEF FPC}
|
|
attr: TCustomAttribute;
|
|
attr: TCustomAttribute;
|
|
|
|
+ {$ENDIF}
|
|
propertyname : string;
|
|
propertyname : string;
|
|
begin
|
|
begin
|
|
Result := aObject;
|
|
Result := aObject;
|
|
@@ -349,18 +424,22 @@ begin
|
|
try
|
|
try
|
|
for rProp in rType.GetProperties do
|
|
for rProp in rType.GetProperties do
|
|
begin
|
|
begin
|
|
|
|
+ {$IFNDEF FPC}
|
|
if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
|
|
if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
|
|
- or ((fSerializeLevel = slPublishedProperty) and (IsPublishedProp(aObject,rProp.Name))) then
|
|
|
|
|
|
+ or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
|
|
|
|
+ {$ENDIF}
|
|
begin
|
|
begin
|
|
if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
|
|
if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
|
|
begin
|
|
begin
|
|
propertyname := rProp.Name;
|
|
propertyname := rProp.Name;
|
|
|
|
+ {$IFNDEF FPC}
|
|
for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
|
|
for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
|
|
if rProp.Name = 'List' then
|
|
if rProp.Name = 'List' then
|
|
begin
|
|
begin
|
|
Result := DeserializeList(Result,propertyname,aJson);
|
|
Result := DeserializeList(Result,propertyname,aJson);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
|
|
+ {$ENDIF}
|
|
Result := DeserializeProperty(Result,propertyname,rProp,aJson);
|
|
Result := DeserializeProperty(Result,propertyname,rProp,aJson);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -377,6 +456,7 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+{$IFNDEF FPC}
|
|
function TJsonSerializer.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
|
|
function TJsonSerializer.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
|
|
var
|
|
var
|
|
ctx : TRttiContext;
|
|
ctx : TRttiContext;
|
|
@@ -403,8 +483,6 @@ begin
|
|
try
|
|
try
|
|
rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
|
|
rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
|
|
i := jarray.Count;
|
|
i := jarray.Count;
|
|
- rProp := rType.GetProperty('Count');
|
|
|
|
- rProp.SetValue(aObject,i);
|
|
|
|
finally
|
|
finally
|
|
jArray.Free;
|
|
jArray.Free;
|
|
end;
|
|
end;
|
|
@@ -424,21 +502,31 @@ begin
|
|
Break;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+ rProp := rType.GetProperty('Count');
|
|
|
|
+ rProp.SetValue(aObject,i);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+{$ENDIF}
|
|
|
|
|
|
function TJsonSerializer.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
|
|
function TJsonSerializer.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
|
|
var
|
|
var
|
|
rValue : TValue;
|
|
rValue : TValue;
|
|
|
|
+ {$IFNDEF FPC}
|
|
member : TJSONPair;
|
|
member : TJSONPair;
|
|
|
|
+ {$ELSE}
|
|
|
|
+ member : TJsonObject;
|
|
|
|
+ {$ENDIF}
|
|
objClass: TClass;
|
|
objClass: TClass;
|
|
jArray : TJSONArray;
|
|
jArray : TJSONArray;
|
|
json : TJSONObject;
|
|
json : TJSONObject;
|
|
- propinfo : PPropInfo;
|
|
|
|
begin
|
|
begin
|
|
Result := aObject;
|
|
Result := aObject;
|
|
|
|
+ rValue := nil;
|
|
|
|
+ {$IFNDEF FPC}
|
|
member := TJSONPair(aJson.GetValue(aName));
|
|
member := TJSONPair(aJson.GetValue(aName));
|
|
|
|
+ {$ELSE}
|
|
|
|
+ member := TJsonObject(aJson.Find(aName));
|
|
|
|
+ {$ENDIF}
|
|
if member <> nil then
|
|
if member <> nil then
|
|
begin
|
|
begin
|
|
case aProperty.PropertyType.TypeKind of
|
|
case aProperty.PropertyType.TypeKind of
|
|
@@ -446,7 +534,12 @@ begin
|
|
begin
|
|
begin
|
|
jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
|
|
jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
|
|
try
|
|
try
|
|
|
|
+ {$IFNDEF FPC}
|
|
aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
|
|
aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
|
|
|
|
+ {$ELSE}
|
|
|
|
+ DeserializeDynArray(aProperty.PropertyType.Handle,aName,Result,jArray);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ Exit;
|
|
finally
|
|
finally
|
|
jArray.Free;
|
|
jArray.Free;
|
|
end;
|
|
end;
|
|
@@ -455,12 +548,20 @@ begin
|
|
begin
|
|
begin
|
|
//if (member.JsonValue is TJSONObject) then
|
|
//if (member.JsonValue is TJSONObject) then
|
|
begin
|
|
begin
|
|
- json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
|
|
|
|
|
|
+ json := TJsonObject(TJSONObject.ParseJSONValue(member.ToJson));
|
|
try
|
|
try
|
|
if aProperty.GetValue(aObject).AsObject = nil then
|
|
if aProperty.GetValue(aObject).AsObject = nil then
|
|
begin
|
|
begin
|
|
|
|
+ {$IFNDEF FPC}
|
|
objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
|
|
objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
|
|
- rValue := DeserializeClass(objClass,json)
|
|
|
|
|
|
+ rValue := DeserializeClass(objClass,json);
|
|
|
|
+ {$ELSE}
|
|
|
|
+ objClass := GetObjectPropClass(aObject,aName);
|
|
|
|
+ //objClass := GetTypeData(aProperty.PropertyType.Handle)^.ClassType;
|
|
|
|
+ rValue := DeserializeClass(objClass,json);
|
|
|
|
+ SetObjectProp(aObject,aName,rValue.AsObject);
|
|
|
|
+ Exit;
|
|
|
|
+ {$ENDIF}
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
@@ -472,6 +573,7 @@ begin
|
|
end;
|
|
end;
|
|
end
|
|
end
|
|
end;
|
|
end;
|
|
|
|
+ {$IFNDEF FPC}
|
|
tkRecord :
|
|
tkRecord :
|
|
begin
|
|
begin
|
|
json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
|
|
json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
|
|
@@ -481,19 +583,29 @@ begin
|
|
json.Free;
|
|
json.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+ {$ENDIF}
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- rValue := DeserializeType(Result,aProperty.PropertyType.TypeKind,aProperty.GetValue(Result).TypeInfo,member.ToJSON);
|
|
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
|
|
|
|
+ {$ELSE}
|
|
|
|
+ rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
|
|
|
|
+ if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
|
|
|
|
+ {$ENDIF}
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+ {$IFNDEF FPC}
|
|
if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
|
|
if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
|
|
|
|
+ {$ENDIF}
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+{$IFNDEF FPC}
|
|
function TJsonSerializer.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
|
|
function TJsonSerializer.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
|
|
var
|
|
var
|
|
i : Integer;
|
|
i : Integer;
|
|
value : string;
|
|
value : string;
|
|
|
|
+ fsettings : TFormatSettings;
|
|
begin
|
|
begin
|
|
try
|
|
try
|
|
value := AnsiDequotedStr(aValue,'"');
|
|
value := AnsiDequotedStr(aValue,'"');
|
|
@@ -530,7 +642,8 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- Result := StrToFloat(value);
|
|
|
|
|
|
+ fsettings := TFormatSettings.Create;
|
|
|
|
+ Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
tkEnumeration :
|
|
tkEnumeration :
|
|
@@ -561,15 +674,97 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+{$ELSE}
|
|
|
|
+function TJsonSerializer.DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
|
|
|
|
+var
|
|
|
|
+ value : string;
|
|
|
|
+ propinfo : PPropInfo;
|
|
|
|
+ fsettings : TFormatSettings;
|
|
|
|
+begin
|
|
|
|
+ try
|
|
|
|
+ value := AnsiDequotedStr(aValue,'"');
|
|
|
|
+
|
|
|
|
+ if value = '' then
|
|
|
|
+ begin
|
|
|
|
+ Result := nil;
|
|
|
|
+ Exit;
|
|
|
|
+ end;
|
|
|
|
+ propinfo := GetPropInfo(aObject,aPropertyName);
|
|
|
|
+ //case propinfo.PropType.Kind of
|
|
|
|
+ case aType of
|
|
|
|
+ tkString, tkLString, tkWString, tkUString, tkAString :
|
|
|
|
+ begin
|
|
|
|
+ Result := value;
|
|
|
|
+ //SetStrProp(aObject,propinfo,value);
|
|
|
|
+ end;
|
|
|
|
+ tkChar, tkWChar :
|
|
|
|
+ begin
|
|
|
|
+ Result := value;
|
|
|
|
+ end;
|
|
|
|
+ tkInteger :
|
|
|
|
+ begin
|
|
|
|
+ Result := StrToInt(value);
|
|
|
|
+ end;
|
|
|
|
+ tkInt64 :
|
|
|
|
+ begin
|
|
|
|
+ Result := StrToInt64(value);
|
|
|
|
+ end;
|
|
|
|
+ tkFloat :
|
|
|
|
+ begin
|
|
|
|
+ if propinfo.PropType = TypeInfo(TDateTime) then
|
|
|
|
+ begin
|
|
|
|
+ Result := JsonDateToDateTime(value);
|
|
|
|
+ end
|
|
|
|
+ else if propinfo.PropType = TypeInfo(TDate) then
|
|
|
|
+ begin
|
|
|
|
+ Result := StrToDate(value);
|
|
|
|
+ end
|
|
|
|
+ else if propinfo.PropType = TypeInfo(TTime) then
|
|
|
|
+ begin
|
|
|
|
+ Result := StrToTime(value);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ fsettings := DefaultFormatSettings;
|
|
|
|
+ Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ tkEnumeration:
|
|
|
|
+ begin
|
|
|
|
+ Result := value;
|
|
|
|
+ end;
|
|
|
|
+ tkBool :
|
|
|
|
+ begin
|
|
|
|
+ Result := StrToBool(value);
|
|
|
|
+ end;
|
|
|
|
+ tkSet :
|
|
|
|
+ begin
|
|
|
|
+ Result := value;
|
|
|
|
+ end;
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ //raise EclJsonSerializerError.Create('Not supported data type!');
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ //if not Result.IsEmpty then SetPropertyValue(aObject,propinfo,Result);
|
|
|
|
+ except
|
|
|
|
+ on E : Exception do
|
|
|
|
+ begin
|
|
|
|
+ raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s" : %s',[aObject.ClassName,e.Message]);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+{$ENDIF}
|
|
|
|
|
|
function TJsonSerializer.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
|
|
function TJsonSerializer.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
|
|
var
|
|
var
|
|
propname : string;
|
|
propname : string;
|
|
|
|
+ cname : string;
|
|
begin
|
|
begin
|
|
Result := True;
|
|
Result := True;
|
|
propname := aPropertyName.ToLower;
|
|
propname := aPropertyName.ToLower;
|
|
-
|
|
|
|
- if (aObject.ClassName.StartsWith('TObjectList')) or (aObject.ClassName.StartsWith('TList')) then
|
|
|
|
|
|
+ cname := aObject.ClassName;
|
|
|
|
+ if (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList')) then
|
|
begin
|
|
begin
|
|
if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
|
|
if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
|
|
end
|
|
end
|
|
@@ -577,24 +772,125 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
function TJsonSerializer.IsGenericList(aObject : TObject) : Boolean;
|
|
function TJsonSerializer.IsGenericList(aObject : TObject) : Boolean;
|
|
|
|
+var
|
|
|
|
+ cname : string;
|
|
|
|
+begin
|
|
|
|
+ cname := aObject.ClassName;
|
|
|
|
+ Result := (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList'));
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TJsonSerializer.GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
|
|
|
|
+var
|
|
|
|
+ pinfo : PPropInfo;
|
|
begin
|
|
begin
|
|
- Result := (aObject.ClassName.StartsWith('TObjectList')) or (aObject.ClassName.StartsWith('TList'));
|
|
|
|
|
|
+ Result := nil;
|
|
|
|
+ pinfo := GetPropInfo(Instance,PropertyName);
|
|
|
|
+ case pinfo.PropType^.Kind of
|
|
|
|
+ tkInteger : Result := GetOrdProp(Instance,pinfo);
|
|
|
|
+ tkInt64 : Result := GetInt64Prop(Instance,PropertyName);
|
|
|
|
+ tkFloat : Result := GetFloatProp(Instance,PropertyName);
|
|
|
|
+ tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
|
|
|
|
+ {$IFDEF FPC}
|
|
|
|
+ tkSString,
|
|
|
|
+ tkAString,
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ tkLString : Result := GetStrProp(Instance,pinfo);
|
|
|
|
+ tkWString : Result := GetWideStrProp(Instance,PropertyName);
|
|
|
|
+ {$IFDEF FPC}
|
|
|
|
+ tkEnumeration : Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName));
|
|
|
|
+ {$ELSE}
|
|
|
|
+ tkEnumeration : Result := GetEnumName(@pinfo.PropType,GetOrdProp(Instance,PropertyName));
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ tkSet : Result := GetSetProp(Instance,pinfo,True);
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ tkClass :
|
|
|
|
+ {$ELSE}
|
|
|
|
+ tkBool : Result := Boolean(GetOrdProp(Instance,pinfo));
|
|
|
|
+ tkObject :
|
|
|
|
+ {$ENDIF} Result := GetObjectProp(Instance,pinfo);
|
|
|
|
+ tkDynArray : Result := GetDynArrayProp(Instance,pinfo);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TJsonSerializer.SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue);
|
|
|
|
+var
|
|
|
|
+ pinfo : PPropInfo;
|
|
|
|
+begin
|
|
|
|
+ pinfo := GetPropInfo(Instance,PropertyName);
|
|
|
|
+ SetPropertyValue(Instance,pinfo,aValue);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TJsonSerializer.SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue);
|
|
|
|
+begin
|
|
|
|
+ case aPropInfo.PropType^.Kind of
|
|
|
|
+ tkInteger : SetOrdProp(Instance,aPropInfo,aValue.AsInteger);
|
|
|
|
+ tkInt64 : SetInt64Prop(Instance,aPropInfo,aValue.AsInt64);
|
|
|
|
+ tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
|
|
|
|
+ tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
|
|
|
|
+ {$IFDEF FPC}
|
|
|
|
+ tkSString,
|
|
|
|
+ tkAString,
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
|
|
|
|
+ tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
|
|
|
|
+ {$IFDEF FPC}
|
|
|
|
+ tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
|
|
|
|
+ tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ tkEnumeration : SetEnumProp(Instance,aPropInfo,aValue.AsString);
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ tkClass :
|
|
|
|
+ {$ELSE}
|
|
|
|
+ tkObject :
|
|
|
|
+ {$ENDIF} SetObjectProp(Instance,aPropInfo,aValue.AsObject);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+{$IFDEF FPC}
|
|
|
|
+procedure TJsonSerializer.LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
|
|
|
|
+type
|
|
|
|
+ TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
|
|
|
|
+const
|
|
|
|
+ Delims = [' ', ',', '[', ']'];
|
|
|
|
+var
|
|
|
|
+ TypeInfo: PTypeInfo;
|
|
|
|
+ W: Cardinal;
|
|
|
|
+ I, N: Integer;
|
|
|
|
+ Count: Integer;
|
|
|
|
+ EnumName: string;
|
|
|
|
+begin
|
|
|
|
+ W := 0;
|
|
|
|
+ TypeInfo := GetTypeData(GetPropType(aPropInfo))^.CompType;
|
|
|
|
+ Count := WordCount(aValue, Delims);
|
|
|
|
+ for N := 1 to Count do
|
|
|
|
+ begin
|
|
|
|
+ EnumName := ExtractWord(N, aValue, Delims);
|
|
|
|
+ try
|
|
|
|
+ I := GetEnumValue(TypeInfo, EnumName);
|
|
|
|
+ if I >= 0 then Include(TCardinalSet(W),I);
|
|
|
|
+ except
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ SetOrdProp(aInstance,aPropInfo,W);
|
|
end;
|
|
end;
|
|
|
|
+{$ENDIF}
|
|
|
|
|
|
function TJsonSerializer.Serialize(aObject: TObject): TJSONObject;
|
|
function TJsonSerializer.Serialize(aObject: TObject): TJSONObject;
|
|
var
|
|
var
|
|
ctx: TRttiContext;
|
|
ctx: TRttiContext;
|
|
|
|
+ {$IFNDEF FPC}
|
|
attr : TCustomAttribute;
|
|
attr : TCustomAttribute;
|
|
|
|
+ comment : string;
|
|
|
|
+ {$ENDIF}
|
|
rType: TRttiType;
|
|
rType: TRttiType;
|
|
rProp: TRttiProperty;
|
|
rProp: TRttiProperty;
|
|
jpair : TJSONPair;
|
|
jpair : TJSONPair;
|
|
ExcludeSerialize : Boolean;
|
|
ExcludeSerialize : Boolean;
|
|
- comment : string;
|
|
|
|
propertyname : string;
|
|
propertyname : string;
|
|
|
|
|
|
- listtype : TRttiType;
|
|
|
|
- listprop : TRttiProperty;
|
|
|
|
- listvalue : TValue;
|
|
|
|
|
|
+ //listtype : TRttiType;
|
|
|
|
+ //listprop : TRttiProperty;
|
|
|
|
+ //listvalue : TValue;
|
|
begin
|
|
begin
|
|
if (aObject = nil) then
|
|
if (aObject = nil) then
|
|
begin
|
|
begin
|
|
@@ -610,8 +906,9 @@ begin
|
|
for rProp in rType.GetProperties do
|
|
for rProp in rType.GetProperties do
|
|
begin
|
|
begin
|
|
ExcludeSerialize := False;
|
|
ExcludeSerialize := False;
|
|
- comment := '';
|
|
|
|
propertyname := rProp.Name;
|
|
propertyname := rProp.Name;
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ comment := '';
|
|
for attr in rProp.GetAttributes do
|
|
for attr in rProp.GetAttributes do
|
|
begin
|
|
begin
|
|
if attr is TNotSerializableProperty then ExcludeSerialize := True
|
|
if attr is TNotSerializableProperty then ExcludeSerialize := True
|
|
@@ -619,13 +916,15 @@ begin
|
|
else if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
|
|
else if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
|
|
end;
|
|
end;
|
|
if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
|
|
if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
|
|
- or ((fSerializeLevel = slPublishedProperty) and (IsPublishedProp(aObject,rProp.Name))) then
|
|
|
|
|
|
+ or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
|
|
|
|
+ {$ENDIF}
|
|
begin
|
|
begin
|
|
if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
|
|
if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
|
|
begin
|
|
begin
|
|
//add comment as pair
|
|
//add comment as pair
|
|
|
|
+ {$IFNDEF FPC}
|
|
if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
|
|
if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
|
|
- //s := rProp.Name;
|
|
|
|
|
|
+ {$ENDIF}
|
|
//listtype := ctx.GetType(rProp.GetValue(aObject).TypeInfo);
|
|
//listtype := ctx.GetType(rProp.GetValue(aObject).TypeInfo);
|
|
//if (listtype.ClassParent.ClassName.StartsWith('TObjectList')) then
|
|
//if (listtype.ClassParent.ClassName.StartsWith('TObjectList')) then
|
|
//begin
|
|
//begin
|
|
@@ -642,10 +941,17 @@ begin
|
|
//end
|
|
//end
|
|
//else
|
|
//else
|
|
begin
|
|
begin
|
|
|
|
+ {$IFNDEF FPC}
|
|
jpair := Serialize(propertyname,rProp.GetValue(aObject));
|
|
jpair := Serialize(propertyname,rProp.GetValue(aObject));
|
|
|
|
+ {$ELSE}
|
|
|
|
+ jpair := Serialize(aObject,rProp.PropertyType.TypeKind,propertyname);
|
|
|
|
+ {$ENDIF}
|
|
//s := jpair.JsonValue.ToString;
|
|
//s := jpair.JsonValue.ToString;
|
|
- if jpair <> nil then Result.AddPair(jpair)
|
|
|
|
- else jpair.Free;
|
|
|
|
|
|
+ if jpair <> nil then
|
|
|
|
+ begin
|
|
|
|
+ Result.AddPair(jpair);
|
|
|
|
+ end
|
|
|
|
+ else jpair.Free;
|
|
end;
|
|
end;
|
|
//Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
|
|
//Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
|
|
//s := Result.ToJSON;
|
|
//s := Result.ToJSON;
|
|
@@ -669,22 +975,32 @@ begin
|
|
TValue.Make(aAddr,aType.Handle,Result);
|
|
TValue.Make(aAddr,aType.Handle,Result);
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TJsonSerializer.Serialize(const aName : string; aValue : TValue): TJSONPair;
|
|
|
|
|
|
+function TJsonSerializer.GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue;
|
|
|
|
+begin
|
|
|
|
+ TValue.Make(aAddr,aTypeInfo,Result);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+{$IFNDEF FPC}
|
|
|
|
+function TJsonSerializer.Serialize(const aName : string; aValue : TValue) : TJSONPair;
|
|
var
|
|
var
|
|
ctx: TRttiContext;
|
|
ctx: TRttiContext;
|
|
|
|
+ {$IFNDEF FPC}
|
|
rRec : TRttiRecordType;
|
|
rRec : TRttiRecordType;
|
|
rField : TRttiField;
|
|
rField : TRttiField;
|
|
rDynArray : TRTTIDynamicArrayType;
|
|
rDynArray : TRTTIDynamicArrayType;
|
|
|
|
+ {$ENDIF}
|
|
json : TJSONObject;
|
|
json : TJSONObject;
|
|
jArray : TJSONArray;
|
|
jArray : TJSONArray;
|
|
jPair : TJSONPair;
|
|
jPair : TJSONPair;
|
|
jValue : TJSONValue;
|
|
jValue : TJSONValue;
|
|
i : Integer;
|
|
i : Integer;
|
|
|
|
+ s : string;
|
|
begin
|
|
begin
|
|
Result := TJSONPair.Create(aName,nil);
|
|
Result := TJSONPair.Create(aName,nil);
|
|
//Result.JsonString := TJSONString(aName);
|
|
//Result.JsonString := TJSONString(aName);
|
|
try
|
|
try
|
|
- case aValue.Kind of
|
|
|
|
|
|
+ case avalue.Kind of
|
|
|
|
+ {$IFNDEF FPC}
|
|
tkDynArray :
|
|
tkDynArray :
|
|
begin
|
|
begin
|
|
jArray := TJSONArray.Create;
|
|
jArray := TJSONArray.Create;
|
|
@@ -708,6 +1024,7 @@ begin
|
|
ctx.Free;
|
|
ctx.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+ {$ENDIF}
|
|
tkClass :
|
|
tkClass :
|
|
begin
|
|
begin
|
|
Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
|
|
Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
|
|
@@ -742,7 +1059,14 @@ begin
|
|
begin
|
|
begin
|
|
Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
|
|
Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
|
|
end
|
|
end
|
|
- else Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
|
|
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
|
|
|
|
+ {$ELSE}
|
|
|
|
+ Result.JsonValue := TJsonFloatNumber.Create(aValue.AsExtended);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
tkEnumeration :
|
|
tkEnumeration :
|
|
begin
|
|
begin
|
|
@@ -752,14 +1076,15 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
|
|
|
|
- //Result.JsonValue := TJSONString.Create(aValue.ToString);
|
|
|
|
|
|
+ //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
|
|
|
|
+ Result.JsonValue := TJSONString.Create(aValue.ToString);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
tkSet :
|
|
tkSet :
|
|
begin
|
|
begin
|
|
Result.JsonValue := TJSONString.Create(aValue.ToString);
|
|
Result.JsonValue := TJSONString.Create(aValue.ToString);
|
|
end;
|
|
end;
|
|
|
|
+ {$IFNDEF FPC}
|
|
tkRecord :
|
|
tkRecord :
|
|
begin
|
|
begin
|
|
rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
|
|
rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
|
|
@@ -774,6 +1099,7 @@ begin
|
|
ctx.Free;
|
|
ctx.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+ {$ENDIF}
|
|
tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
|
|
tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
|
|
begin
|
|
begin
|
|
//skip these properties
|
|
//skip these properties
|
|
@@ -781,19 +1107,202 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- raise EJsonSerializeError.Create(Format(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]));
|
|
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ raise EJsonSerializeError.CreateFmt(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]);
|
|
|
|
+ {$ELSE}
|
|
|
|
+ //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
|
|
|
|
+ {$ENDIF}
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
except
|
|
except
|
|
on E : Exception do
|
|
on E : Exception do
|
|
begin
|
|
begin
|
|
Result.Free;
|
|
Result.Free;
|
|
|
|
+ {$IFNDEF FPC}
|
|
raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
|
|
raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
|
|
|
|
+ {$ENDIF}
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+{$ELSE}
|
|
|
|
+function TJsonSerializer.GetPropType(aPropInfo: PPropInfo): PTypeInfo;
|
|
|
|
+begin
|
|
|
|
+ Result := aPropInfo^.PropType;
|
|
|
|
+end;
|
|
|
|
|
|
|
|
+function TJsonSerializer.FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
|
|
|
|
+const
|
|
|
|
+ Precisions: array[TFloatType] of Integer = (7, 15, 18, 18, 19);
|
|
|
|
+var
|
|
|
|
+ fsettings : TFormatSettings;
|
|
|
|
+begin
|
|
|
|
+ fsettings := FormatSettings;
|
|
|
|
+ Result := StringReplace(FloatToStrF(GetFloatProp(aObject, aPropInfo), ffGeneral,
|
|
|
|
+ Precisions[GetTypeData(GetPropType(aPropInfo))^.FloatType],0),
|
|
|
|
+ '.',fsettings.DecimalSeparator,[rfReplaceAll]);
|
|
|
|
+end;
|
|
|
|
|
|
|
|
+function TJsonSerializer.Serialize(const aName : string; aValue : TValue) : TJSONPair;
|
|
|
|
+begin
|
|
|
|
+ Result := TJSONPair.Create(aName,nil);
|
|
|
|
+ //Result.JsonString := TJSONString(aName);
|
|
|
|
+ try
|
|
|
|
+ case avalue.Kind of
|
|
|
|
+ tkInteger, tkInt64 :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
|
|
|
|
+ end;
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ except
|
|
|
|
+ Result.Free;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TJsonSerializer.Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
|
|
|
|
+var
|
|
|
|
+ propinfo : PPropInfo;
|
|
|
|
+ jArray : TJsonArray;
|
|
|
|
+ jPair : TJsonPair;
|
|
|
|
+ jValue : TJsonValue;
|
|
|
|
+ i : Integer;
|
|
|
|
+ pArr : Pointer;
|
|
|
|
+ rValue : TValue;
|
|
|
|
+ rItemValue : TValue;
|
|
|
|
+ len : Integer;
|
|
|
|
+begin
|
|
|
|
+ try
|
|
|
|
+ Result := TJSONPair.Create(aPropertyName,nil);
|
|
|
|
+
|
|
|
|
+ propinfo := GetPropInfo(aObject,aPropertyName);
|
|
|
|
+ //case propinfo.PropType.Kind of
|
|
|
|
+ case aType of
|
|
|
|
+ tkDynArray :
|
|
|
|
+ begin
|
|
|
|
+ len := 0;
|
|
|
|
+ jArray := TJSONArray.Create;
|
|
|
|
+ try
|
|
|
|
+ pArr := GetDynArrayProp(aObject,aPropertyName);
|
|
|
|
+ TValue.Make(@pArr,propinfo.PropType, rValue);
|
|
|
|
+ if rValue.IsArray then len := rValue.GetArrayLength;
|
|
|
|
+ for i := 0 to len - 1 do
|
|
|
|
+ begin
|
|
|
|
+ rItemValue := rValue.GetArrayElement(i);
|
|
|
|
+ jPair := Serialize(aPropertyName,rItemValue);
|
|
|
|
+ try
|
|
|
|
+ //jValue := TJsonValue(jPair.JsonValue.Clone);
|
|
|
|
+ jValue := jPair.JsonValue;
|
|
|
|
+ jArray.Add(jValue);
|
|
|
|
+ //jPair.JsonValue.Owned := False;
|
|
|
|
+ finally
|
|
|
|
+ jPair.Free;
|
|
|
|
+ //jValue.Owned := True;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ Result.JsonValue := jArray;
|
|
|
|
+ finally
|
|
|
|
+ DynArrayClear(pArr,propinfo.PropType);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ tkClass :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONValue(Serialize(GetObjectProp(aObject,aPropertyName)));
|
|
|
|
+ end;
|
|
|
|
+ tkString, tkLString, tkWString, tkUString, tkAString :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
|
|
|
|
+ end;
|
|
|
|
+ tkChar, tkWChar :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
|
|
|
|
+ end;
|
|
|
|
+ tkInteger :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
|
|
|
|
+ end;
|
|
|
|
+ tkInt64 :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
|
|
|
|
+ end;
|
|
|
|
+ tkFloat :
|
|
|
|
+ begin
|
|
|
|
+ if propinfo.PropType = TypeInfo(TDateTime) then
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
|
|
|
|
+ end
|
|
|
|
+ else if propinfo.PropType = TypeInfo(TDate) then
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
|
|
|
|
+ end
|
|
|
|
+ else if propinfo.PropType = TypeInfo(TTime) then
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
|
|
|
|
+ Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ tkEnumeration,tkBool :
|
|
|
|
+ begin
|
|
|
|
+ if (propinfo.PropType = System.TypeInfo(Boolean)) then
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)));
|
|
|
|
+ //Result.JsonValue := TJSONString.Create(aValue.ToString);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ tkSet :
|
|
|
|
+ begin
|
|
|
|
+ Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
|
|
|
|
+ end;
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ tkRecord :
|
|
|
|
+ begin
|
|
|
|
+ rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
|
|
|
|
+ try
|
|
|
|
+ json := TJSONObject.Create;
|
|
|
|
+ for rField in rRec.GetFields do
|
|
|
|
+ begin
|
|
|
|
+ json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
|
|
|
|
+ end;
|
|
|
|
+ Result.JsonValue := json;
|
|
|
|
+ finally
|
|
|
|
+ ctx.Free;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
|
|
|
|
+ begin
|
|
|
|
+ //skip these properties
|
|
|
|
+ FreeAndNil(Result);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+
|
|
|
|
+ //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ except
|
|
|
|
+ on E : Exception do
|
|
|
|
+ begin
|
|
|
|
+ Result.Free;
|
|
|
|
+ {$IFNDEF FPC}
|
|
|
|
+ raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+{$ENDIF}
|
|
|
|
+
|
|
|
|
+{$IFNDEF FPC}
|
|
{ TCommentProperty }
|
|
{ TCommentProperty }
|
|
|
|
|
|
constructor TCommentProperty.Create(const aComment: string);
|
|
constructor TCommentProperty.Create(const aComment: string);
|
|
@@ -807,6 +1316,8 @@ constructor TCustomNameProperty.Create(const aName: string);
|
|
begin
|
|
begin
|
|
fName := aName;
|
|
fName := aName;
|
|
end;
|
|
end;
|
|
|
|
+{$ENDIF}
|
|
|
|
+
|
|
|
|
|
|
end.
|
|
end.
|
|
|
|
|