- Some cleanup, added first call to the sample project about the jsonrpc support for record types

This commit is contained in:
Daniele Teti 2022-07-11 00:09:59 +02:00
parent 66211feb75
commit 08bf440713
7 changed files with 97 additions and 101 deletions

View File

@ -330,6 +330,7 @@ type
TMyEnum = (EnumItem1, EnumItem2, EnumItem3);
TMySet = set of TMyEnum;
[MVCNameCase(ncCamelCase)]
TSimpleRecord = record
StringProperty: String;
IntegerProperty: Integer;
@ -343,6 +344,7 @@ type
SetProperty: TMySet;
class function Create: TSimpleRecord; overload; static;
class function Create(Value: Integer): TSimpleRecord; overload; static;
function ToString: String;
end;
TSimpleRecordDynArray = TArray<TSimpleRecord>;
@ -371,7 +373,7 @@ implementation
uses
System.SysUtils,
System.Math,
RandomUtilsU, FireDAC.Comp.Client;
RandomUtilsU, FireDAC.Comp.Client, System.TypInfo;
{ TPerson }
@ -786,6 +788,31 @@ begin
Result.CurrencyProperty := Value + Value div 1000;
end;
function TSimpleRecord.ToString: String;
function SetToString: String;
var
lEl: TMyEnum;
begin
for lEl in SetProperty do
begin
Result := Result + GetEnumName(typeinfo(TMyEnum), Ord(Self.EnumProperty)) + ',';
end;
Result := Result.Trim([',']);
end;
begin
Result :=
'StringProperty = ' + Self.StringProperty + sLineBreak +
'IntegerProperty = ' + Self.IntegerProperty.ToString + sLineBreak +
'FloatProperty = ' + Self.FloatProperty.ToString + sLineBreak +
'CurrencyProperty = ' + Self.CurrencyProperty.ToString + sLineBreak +
'DateProperty = ' + DateToStr(Self.DateProperty) + sLineBreak +
'TimeProperty = ' + TimeToStr(Self.TimeProperty) + sLineBreak +
'DateTimeProperty = ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Self.DateTimeProperty) + sLineBreak +
'BooleanProperty = ' + BoolToStr(Self.BooleanProperty, True) + sLineBreak +
'EnumProperty = ' + GetEnumName(typeinfo(TMyEnum), Ord(Self.EnumProperty)) + sLineBreak +
'SetProperty = ' + SetToString + sLineBreak;
end;
{ TComplexRecord }
class function TComplexRecord.Create: TComplexRecord;

View File

@ -17,7 +17,7 @@ object MainForm: TMainForm
Top = 0
Width = 842
Height = 604
ActivePage = TabSheet1
ActivePage = TabSheet6
Align = alClient
TabOrder = 0
object TabSheet1: TTabSheet
@ -523,6 +523,31 @@ object MainForm: TMainForm
OnClick = btnGenericExcWithoutCustomHandlingClick
end
end
object TabSheet6: TTabSheet
Caption = 'Using record as parameters'
ImageIndex = 3
DesignSize = (
834
576)
object btnSingleRec: TButton
Left = 16
Top = 16
Width = 185
Height = 41
Caption = 'Returning Single Record'
TabOrder = 0
OnClick = btnSingleRecClick
end
object lbLogRec: TListBox
Left = 216
Top = 16
Width = 601
Height = 545
Anchors = [akLeft, akTop, akRight, akBottom]
ItemHeight = 13
TabOrder = 1
end
end
end
object DataSource1: TDataSource
DataSet = FDMemTable1

View File

@ -92,6 +92,9 @@ type
btnGenericExcWithCustomHandling: TButton;
btnGenericExcWithCustomHAndling2: TButton;
btnGenericExcWithoutCustomHandling: TButton;
TabSheet6: TTabSheet;
btnSingleRec: TButton;
lbLogRec: TListBox;
procedure btnSubstractClick(Sender: TObject);
procedure btnReverseStringClick(Sender: TObject);
procedure edtGetCustomersClick(Sender: TObject);
@ -116,6 +119,7 @@ type
procedure btnGenericExcWithCustomHandlingClick(Sender: TObject);
procedure btnGenericExcWithCustomHAndling2Click(Sender: TObject);
procedure btnGenericExcWithoutCustomHandlingClick(Sender: TObject);
procedure btnSingleRecClick(Sender: TObject);
private
FExecutor: IMVCJSONRPCExecutor;
// FExecutor2: IMVCJSONRPCExecutor;
@ -140,7 +144,7 @@ uses
MVCFramework.DataSet.Utils,
BusinessObjectsU,
System.Math,
System.Rtti;
System.Rtti, CommonTypesU;
{$R *.dfm}
@ -371,6 +375,22 @@ begin
// lbPerson.Items.Add('DOB:'.PadRight(15) + DateToStr(lJSON.D['dob']));
end;
procedure TMainForm.btnSingleRecClick(Sender: TObject);
var
lReq: IJSONRPCRequest;
lResp: IJSONRPCResponse;
lPersonRec: TPersonRec;
begin
lReq := TJSONRPCRequest.Create;
lReq.Method := 'GetPersonRec';
lReq.RequestID := Random(1000);
lResp := FExecutor.ExecuteRequest('/jsonrpc', lReq);
lPersonRec := TMVCRecordUtils.JSONObjectToRecord<TPersonRec>(lResp.ResultAsJSONObject);
lbLogRec.Items.Add('** TPersonRec **');
lbLogRec.Items.Add(lResp.ResultAsJSONObject.ToJSON());
lbLogRec.Items.Add(lPersonRec.ToString);
end;
procedure TMainForm.btnSubstractClick(Sender: TObject);
var
lReq: IJSONRPCRequest;

View File

@ -33,54 +33,9 @@ uses
BusinessObjectsU,
FireDAC.Comp.Client,
MVCFramework.Serializer.Commons,
MVCFramework.Commons, MVCFramework, MVCFramework.JSONRPC;
MVCFramework.Commons, MVCFramework, MVCFramework.JSONRPC, CommonTypesU;
type
TPersonType = (ptFamily, ptFriend, ptColleague, ptAcquaintance);
TPersonTypes = set of TPersonType;
[MVCNameCase(ncCamelCase)]
TChildRec = record
ChildName: String;
PersonType: TPersonType;
ChildSurname: String;
end;
[MVCNameCase(ncCamelCase)]
TPersonRec = record
Name: String;
Surname: String;
// [MVCNameAs('personAge')]
Age: Integer;
Child: TChildRec;
PersonType: TPersonType;
InitialTypes: TPersonTypes;
end;
TPeopleList = TArray<TPersonRec>;
TPeopleArray = array [0..1] of TPersonRec;
TVendorProxy = record
Code: String;
FileAs: String;
IsDefault: Boolean;
InActive: Boolean;
Name: String;
OID: Integer;
UsageNotes: String;
end;
TVendorProxyList = TArray<TVendorProxy>;
TVendorPersonLink = record
PersonOID: Integer;
DefaultVendorOID: Integer;
LinkedVendorList: TArray<Integer>;
end;
TVendorProxiesAndLinks = record
VendorList: TArray<TVendorProxy>;
PersonLinkList: TArray<TVendorPersonLink>;
end;
TMyObject = class
private
@ -322,6 +277,8 @@ begin
Result.Age := 42;
Result.Child.ChildName := 'Mattia';
Result.Child.ChildSurname := 'Teti';
Result.PersonType := ptFriend;
Result.InitialTypes := [ptFriend, ptColleague];
end;
// function TMyObject.GetPeopleDataset: TFDMemTable;

View File

@ -5,7 +5,8 @@ uses
MainClientFormU in 'MainClientFormU.pas' {MainForm},
MVCFramework.JSONRPC.Client in '..\..\sources\MVCFramework.JSONRPC.Client.pas',
RandomUtilsU in '..\commons\RandomUtilsU.pas',
BusinessObjectsU in '..\commons\BusinessObjectsU.pas';
BusinessObjectsU in '..\commons\BusinessObjectsU.pas',
CommonTypesU in 'CommonTypesU.pas';
{$R *.res}

View File

@ -17,7 +17,8 @@ uses
MVCFramework.JSONRPC in '..\..\sources\MVCFramework.JSONRPC.pas',
BusinessObjectsU in '..\commons\BusinessObjectsU.pas',
RandomUtilsU in '..\commons\RandomUtilsU.pas',
MainDM in '..\articles_crud_server\MainDM.pas' {dmMain: TDataModule};
MainDM in '..\articles_crud_server\MainDM.pas' {dmMain: TDataModule},
CommonTypesU in 'CommonTypesU.pas';
{$R *.res}

View File

@ -1701,10 +1701,8 @@ var
lOutInteger: Integer;
lInt: Integer;
lOutInteger64: Int64;
ChildObject: TObject;
lChildObject: TObject;
lRef: PByte;
I: Integer;
lInnerName: String;
lInnerType: TRttiType;
lCtx: TRttiContext;
lArr: TArray<TValue>;
@ -1733,6 +1731,7 @@ var
end;
end;
begin
lChildObject := nil;
case AJsonObject[APropertyName].Typ of
jdtNone:
Exit;
@ -1920,13 +1919,13 @@ begin
case AValue.Kind of
tkInterface:
begin
JsonObjectToObject(AJsonObject.O[APropertyName], ChildObject,
GetSerializationType(ChildObject, AType), AIgnored);
JsonObjectToObject(AJsonObject.O[APropertyName], lChildObject,
GetSerializationType(lChildObject, AType), AIgnored);
end;
tkClass:
begin
JsonObjectToObject(AJsonObject.O[APropertyName], ChildObject, GetSerializationType(ChildObject, AType),
AIgnored);
JsonObjectToObject(AJsonObject.O[APropertyName], lChildObject,
GetSerializationType(lChildObject, AType), AIgnored);
end;
tkString, tkUString:
begin
@ -1971,23 +1970,8 @@ begin
Format('Wrong array size, expected %d, got %d',
[AValue.GetArrayLength, AJSONObject.A[APropertyName].Count]));
end;
var lt := ARTTIField.FieldType.Handle;
SetLength(lArr, AJSONObject.A[APropertyName].Count);
BuildATValueArrayFromJSONArrayOfJSONObject;
// lInnerType := lCtx.GetType(AValue.GetArrayElement(0).TypeInfo);
// lInnerTypeAsRecord := lInnerType.AsRecord;
// for I := 0 to Length(lArr) - 1 do
// begin
// lBuff := AValue.GetReferenceToRawArrayElement(I);
// lJItem := AJSONObject.A[APropertyName].Items[I].ObjectValue;
// JSONObjectToRecord(
// lJItem,
// lInnerTypeAsRecord,
// lBuff
// );
// TValue.MakeWithoutCopy(lBuff, lInnerType.Handle, lArr[I]);
// FreeMem(lBuff, lInnerType.TypeSize);
// end;
AValue := TValue.FromArray(ARTTIField.FieldType.Handle, lArr);
end
else if AValue.Kind = tkDynArray then
@ -1995,24 +1979,12 @@ begin
SetLength(lArr, AJSONObject.A[APropertyName].Count);
if Length(lArr) > 0 then
begin
//DT: This code is required to know the typeinfo of an element of the dynamic array
//still not created. This is required because the dynamic array is still
//not dimensioned, for a static array this is not necessary.
//DT: This line is required to know the typeinfo of an element of the dynamic array
//still not created (see BuildATValueArrayFromJSONArrayOfJSONObject).
//This is required because the dynamic array is still
//not dimensioned here, for a static array this is not necessary.
AValue := TValue.FromArray(ARTTIField.FieldType.Handle, [TValue.Empty]);
BuildATValueArrayFromJSONArrayOfJSONObject;
// lInnerType := lCtx.GetType(AValue.GetArrayElement(0).TypeInfo);
// lInnerTypeAsRecord := lInnerType.AsRecord;
// for I := 0 to Length(lArr) - 1 do
// begin
// lJItem := AJSONObject.A[APropertyName].Items[I].ObjectValue;
// JSONObjectToRecord(
// lJItem,
// lInnerTypeAsRecord,
// lBuff
// );
// TValue.MakeWithoutCopy(lBuff, lInnerType.Handle, lArr[I]);
// FreeMem(lBuff, lInnerType.TypeSize);
// end;
end;
AValue := TValue.FromArray(ARTTIField.FieldType.Handle, lArr);
end
@ -2047,12 +2019,6 @@ begin
continue;
lName := TMVCSerializerHelper.ApplyNameCase(GetNameCase(ADataSet, ANameCase), lName { Field.FieldName } );
// case GetNameCase(ADataSet, ANameCase) of
// ncLowerCase:
// name := LowerCase(Field.FieldName);
// ncUpperCase:
// name := UpperCase(Field.FieldName);
// end;
if not AJsonObject.Contains(lName) then
continue;
@ -2384,25 +2350,24 @@ begin
end;
procedure TMVCJsonDataObjectsSerializer.JSONObjectToNestedRecordfield(
procedure TMVCJsonDataObjectsSerializer.JSONObjectToNestedRecordField(
const JSONObject: TJsonObject; RecordFieldRTTIType: TRttiField; const TypeOffset: Integer; var Buffer: PByte);
var
lChildType: TRttiType;
lChildFieldOffset: Integer;
lKeyName: String;
lValue: TValue;
lField: TRttiField;
begin
if RecordFieldRTTIType.FieldType.TypeKind <> tkRecord then
begin
raise EMVCDeserializationException.Create('Only record type allowed');
end;
//Recupero il tipo e l'offset
lChildType := RecordFieldRTTIType.FieldType;
lChildFieldOffset := RecordFieldRTTIType.Offset + TypeOffset;
//recupero i campi
for var lField in lChildType.GetFields do
for lField in lChildType.GetFields do
begin
lKeyName := TMVCSerializerHelper.GetKeyName(lField, lChildType);
lValue := lField.GetValue(Buffer + lChildFieldOffset);
@ -2417,9 +2382,9 @@ procedure TMVCJsonDataObjectsSerializer.JSONObjectToNestedRecordFieldStatic(
const TypeOffset: Integer; var Buffer: PByte);
var
lChildType: TRttiType;
// lChildFieldOffset: Integer;
lKeyName: String;
lValue: TValue;
lField: TRttiField;
begin
if RecordFieldRTTIType.FieldType.TypeKind <> tkRecord then
begin
@ -2431,7 +2396,7 @@ begin
// lChildFieldOffset := RecordFieldRTTIType.Offset + TypeOffset;
//recupero i campi
for var lField in lChildType.GetFields do
for lField in lChildType.GetFields do
begin
lKeyName := TMVCSerializerHelper.GetKeyName(lField, lChildType);
lValue := lField.GetValue(Buffer); // + lChildFieldOffset);