Skip to content

Commit

Permalink
Added MVCNameCaseDefault global config variable (with updated tests a…
Browse files Browse the repository at this point in the history
…nd wizard)
  • Loading branch information
danieleteti committed Jun 8, 2024
1 parent b1e8c98 commit 07e16a3
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 73 deletions.
19 changes: 13 additions & 6 deletions ideexpert/DMVC.Expert.CodeGen.Commands.pas
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ procedure TUnitProgramCommand.ExecuteInterface(
.AppendLine(' MVCFramework,')
.AppendLine(' MVCFramework.Logger,')
.AppendLine(' MVCFramework.DotEnv,')
.AppendLine(' MVCFramework.Commons,');
.AppendLine(' MVCFramework.Commons,')
.AppendLine(' MVCFramework.Serializer.Commons,');
if Model.B[TConfigKey.program_ssv_mustache] then
begin
Section
Expand Down Expand Up @@ -403,7 +404,6 @@ procedure TUnitControllerEntityDeclarationCommand.ExecuteInterface(Section: TStr
.AppendLine(' MVCFramework.Nullables, MVCFramework.Serializer.Commons;')
.AppendLine
.AppendLine('type')
.AppendLine(' [MVCNameCase(ncCamelCase)]')
.AppendLine(' ' + Model[TConfigKey.entity_classname] + ' = class')
.AppendLine(' private')
.AppendLine(' fID: NullableInt32;')
Expand Down Expand Up @@ -993,12 +993,19 @@ procedure TUnitMainBeginEndCommand.ExecuteImplementation(Section: TStringBuilder
.AppendLine(' { Enable ReportMemoryLeaksOnShutdown during debug }')
.AppendLine(' // ReportMemoryLeaksOnShutdown := True;')
.AppendLine(' IsMultiThread := True;')
.AppendLine(' // DMVCFramework Specific Configuration ')
.AppendLine(' // When MVCSerializeNulls = True empty nullables and nil are serialized as json null.')
.AppendLine(' // When MVCSerializeNulls = False empty nullables and nil are not serialized at all.')
.AppendLine()
.AppendLine(' // DMVCFramework Specific Configurations ')
.AppendLine(' // When MVCSerializeNulls = True empty nullables and nil are serialized as json null.')
.AppendLine(' // When MVCSerializeNulls = False empty nullables and nil are not serialized at all.')
.AppendLine(' MVCSerializeNulls := True;')
.AppendLine()
.AppendLine(' // MVCNameCaseDefault defines the name case of property names generated by the serializers.')
.AppendLine(' // Possibile values are: ncAsIs, ncUpperCase, ncLowerCase (default), ncCamelCase, ncPascalCase, ncSnakeCase')
.AppendLine(' MVCNameCaseDefault := TMVCNameCase.ncLowerCase;')
.AppendLine()
.AppendLine(' // UseConsoleLogger defines if logs must be emitted to also the console (if available).')
.AppendLine(' UseConsoleLogger := True;')
.AppendLine
.AppendLine()
.AppendLine(' LogI(''** DMVCFramework Server ** build '' + DMVCFRAMEWORK_VERSION);');

if Model.B[TConfigKey.program_dotenv] then
Expand Down
3 changes: 1 addition & 2 deletions sources/MVCFramework.Commons.pas
Original file line number Diff line number Diff line change
Expand Up @@ -825,10 +825,9 @@ implementation
System.NetEncoding,
System.Character,
MVCFramework.Serializer.JsonDataObjects,
MVCFramework.Serializer.Commons,
MVCFramework.Utils,
System.RegularExpressions,
MVCFramework.Logger;
MVCFramework.Logger, MVCFramework.Serializer.Commons;

var
GlobalAppName, GlobalAppPath, GlobalAppExe: string;
Expand Down
44 changes: 22 additions & 22 deletions sources/MVCFramework.DataSet.Utils.pas
Original file line number Diff line number Diff line change
Expand Up @@ -47,57 +47,57 @@ interface
TDataSetHelper = class helper for TDataSet
public
procedure LoadFromTValue(const Value: TValue;
const aNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase);
function AsJSONArray(FieldNameCase: TMVCNameCase = ncLowerCase): string;
function AsJDOJSONArray(FieldNameCase: TMVCNameCase = ncLowerCase)
const aNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault);
function AsJSONArray(FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault): string;
function AsJDOJSONArray(FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault)
: TJDOJsonArray;
function MetadataAsJSONObject(FieldNameCase: TMVCNameCase = ncLowerCase)
function MetadataAsJSONObject(FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault)
: TJSONObject;
function AsJSONArrayOfValues: TJDOJsonArray;
function AsJSONArrayString: string; deprecated 'Use AsJSONArray';
function AsJSONObject(FieldNameCase: TMVCNameCase = ncLowerCase;
function AsJSONObject(FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault;
const IgnoredFields: TArray<string> = nil): string;
function AsJSONObjectString: string; deprecated 'Use AsJSONObject';
procedure LoadFromJSONObject(const JSONObject: TJSONObject;
const FieldNameCase: TMVCNameCase); overload;
procedure LoadFromJSONObject(const JSONObject: TJSONObject;
const AIgnoredFields: TArray<string> = nil;
const FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
const FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;

procedure LoadFromJSONArray(AJSONArray: string;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;
procedure LoadFromJSONArray(AJSONArray: TJSONArray;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;

procedure LoadJSONArrayFromJSONObjectProperty(PropertyName: string;
JSONObject: string;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;
procedure LoadJSONArrayFromJSONObjectProperty(PropertyName: string;
JSONObject: TJSONObject;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;

procedure LoadJSONObjectFromJSONObjectProperty(PropertyName: string;
JSONObject: string;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;
procedure LoadJSONObjectFromJSONObjectProperty(PropertyName: string;
JSONObject: TJSONObject;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;

procedure LoadFromJSONArrayString(AJSONArrayString: string;
AIgnoredFields: TArray<string>;
FieldNameCase: TMVCNameCase = ncLowerCase); overload; deprecated;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload; deprecated;
procedure LoadFromJSONArrayString(AJSONArrayString: string;
FieldNameCase: TMVCNameCase = ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;
procedure LoadFromJSONObjectString(AJSONObjectString: string); overload;
procedure LoadFromJSONObjectString(const JSONObjectString: string;
const IgnoredFields: TArray<string>;
const FieldNameCase: TMVCNameCase = ncLowerCase); overload;
const FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;
// procedure LoadJSONArrayFromJSONObjectProperty(const AJSONObjectString: string; const aPropertyName: string;
// const FieldNameCase: TMVCNameCase = ncLowerCase);
// const FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase);
procedure AppendFromJSONArrayString(AJSONArrayString: string); overload;
procedure AppendFromJSONArrayString(AJSONArrayString: string;
AIgnoredFields: TArray<string>;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncLowerCase); overload;
FieldNameCase: TMVCNameCase = TMVCNameCase.ncUseDefault); overload;
function AsObjectList<T: class, constructor>(CloseAfterScroll
: boolean = false; OwnsObjects: boolean = true): TObjectList<T>;
function AsObject<T: class, constructor>(CloseAfterScroll
Expand All @@ -117,7 +117,7 @@ TDataSetUtils = class sealed
ACloseDataSetAfterScroll: boolean = true);
end;

[MVCNameCase(ncLowerCase)]
[MVCNameCase(ncUseDefault)]
TDataSetHolder = class
private
fDataSet: TDataSet;
Expand Down Expand Up @@ -191,7 +191,7 @@ procedure TDataSetHelper.LoadFromTValue(const Value: TValue;
lSer := TMVCJsonDataObjectsSerializer.Create;
try
lSer.JsonArrayToDataSet(TJSONArray(Value.AsObject), Self, [],
TMVCNameCase.ncLowerCase);
TMVCNameCase.ncUseDefault);
finally
lSer.Free;
end;
Expand All @@ -213,7 +213,7 @@ procedure TDataSetHelper.LoadFromTValue(const Value: TValue;
// end;

function TDataSetHelper.AsJDOJSONArray(FieldNameCase
: TMVCNameCase = ncLowerCase): TJDOJsonArray;
: TMVCNameCase = TMVCNameCase.ncUseDefault): TJDOJsonArray;
var
lSerializer: TMVCJsonDataObjectsSerializer;
begin
Expand Down Expand Up @@ -256,7 +256,7 @@ function TDataSetHelper.AsJSONArrayOfValues: TJDOJsonArray;
end;

function TDataSetHelper.AsJSONArray(FieldNameCase
: TMVCNameCase = ncLowerCase): string;
: TMVCNameCase = TMVCNameCase.ncUseDefault): string;
var
lSerializer: IMVCSerializer;
begin
Expand Down Expand Up @@ -285,7 +285,7 @@ function TDataSetHelper.AsJSONObject(FieldNameCase: TMVCNameCase;

function TDataSetHelper.AsJSONObjectString: string;
begin
Result := AsJSONObject(ncLowerCase);
Result := AsJSONObject(ncUseDefault);
end;

function TDataSetHelper.AsObject<T>(CloseAfterScroll: boolean): T;
Expand Down
4 changes: 2 additions & 2 deletions sources/MVCFramework.JSONRPC.pas
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ procedure AppendTValueToJsonArray(const Value: TValue; const ParamType: TJSONRPC
try
lJArr := TJDOJsonArray.Create;
JSONArr.Add(lJArr);
lSer.DataSetToJsonArray(TDataSet(Value.AsObject), lJArr, TMVCNameCase.ncLowerCase, []);
lSer.DataSetToJsonArray(TDataSet(Value.AsObject), lJArr, TMVCNameCase.ncUseDefault, []);
finally
lSer.Free;
end
Expand Down Expand Up @@ -680,7 +680,7 @@ procedure AppendTValueToJsonObject(const Value: TValue; const Name: string; cons
begin
lSer := TMVCJsonDataObjectsSerializer.Create;
try
lSer.DataSetToJsonArray(TDataSet(Value.AsObject), JSONObj.A[name], TMVCNameCase.ncLowerCase, []);
lSer.DataSetToJsonArray(TDataSet(Value.AsObject), JSONObj.A[name], TMVCNameCase.ncUseDefault, []);
finally
lSer.Free;
end
Expand Down
53 changes: 31 additions & 22 deletions sources/MVCFramework.Serializer.Commons.pas
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ interface
MVCFramework.Commons,
Data.DB,
System.Generics.Collections,
JsonDataObjects, MVCFramework.DuckTyping;
JsonDataObjects,
MVCFramework.DuckTyping;

type
EMVCSerializationException = class(EMVCException)
Expand All @@ -59,7 +60,7 @@ EMVCDeserializationException = class(EMVCException)

TMVCSerializationType = (stUnknown, stDefault, stProperties, stFields);

TMVCNameCase = (ncAsIs, ncUpperCase, ncLowerCase, ncCamelCase, ncPascalCase, ncSnakeCase);
TMVCNameCase = (ncUseDefault, ncAsIs, ncUpperCase, ncLowerCase, ncCamelCase, ncPascalCase, ncSnakeCase);

TMVCDataType = (dtObject, dtArray);

Expand Down Expand Up @@ -203,7 +204,7 @@ TMVCSerializerHelper = record
private
{ private declarations }
public
class function ApplyNameCase(const NameCase: TMVCNameCase; const Value: string): string; static;
class function ApplyNameCase(NameCase: TMVCNameCase; const Value: string): string; static; inline;
class function GetKeyName(const AField: TRttiField; const AType: TRttiType): string;
overload; static;
class function GetKeyName(const AProperty: TRttiProperty; const AType: TRttiType): string;
Expand All @@ -212,9 +213,9 @@ TMVCSerializerHelper = record
class function HasAttribute<T: class>(const AMember: TRttiObject; out AAttribute: T): Boolean;
overload; static;
class function AttributeExists<T: TCustomAttribute>(const AAttributes: TArray<TCustomAttribute>;
out AAttribute: T): Boolean; overload; static;
out AAttribute: T): Boolean; overload; static; inline;
class function AttributeExists<T: TCustomAttribute>(const AAttributes: TArray<TCustomAttribute>)
: Boolean; overload; static;
: Boolean; overload; static; inline;

class procedure EncodeStream(AInput, AOutput: TStream); static;
class procedure DecodeStream(AInput, AOutput: TStream); static;
Expand Down Expand Up @@ -243,14 +244,14 @@ TMVCSerializerHelper = record
end;

// Well Known Response Objects
[MVCNameCase(ncLowerCase)]
[MVCNameCase(ncUseDefault)]
TMVCResponseBase = class abstract(TInterfacedObject, IMVCResponseData)
protected
function GetMetadata: TMVCStringDictionary; virtual; abstract;
function GetData: TObject; virtual; abstract;
end;

[MVCNameCase(ncLowerCase)]
[MVCNameCase(ncUseDefault)]
TMVCTask = class
private
fID: string;
Expand All @@ -261,7 +262,7 @@ TMVCTask = class
constructor Create(const HREF, ID: string);
end;

[MVCNameCase(ncLowerCase)]
[MVCNameCase(ncUseDefault)]
TMVCAcceptedResponse = class(TMVCResponseBase)
private
fTask: TMVCTask;
Expand All @@ -272,7 +273,7 @@ TMVCAcceptedResponse = class(TMVCResponseBase)
destructor Destroy; override;
end;

[MVCNameCase(ncLowerCase)]
[MVCNameCase(ncUseDefault)]
TMVCResponseData = class(TMVCResponseBase, IMVCResponseData)
private
fData: TObject;
Expand Down Expand Up @@ -316,7 +317,7 @@ TMVCObjectResponse = class(TMVCResponseData)
function Add(const Name: string; const Value: TDataset;
const SerializationAction: TMVCDataSetSerializationAction = nil;
const DataSetSerializationType: TMVCDatasetSerializationType = dstAllRecords;
const NameCase: TMVCNameCase = TMVCNameCase.ncLowerCase;
const NameCase: TMVCNameCase = TMVCNameCase.ncUseDefault;
const AIgnoredFields: TMVCIgnoredList = nil): IMVCObjectDictionary; overload;
function TryGetValue(const Name: string; out Value: TObject): Boolean; overload;
function Count: Integer;
Expand Down Expand Up @@ -378,7 +379,7 @@ TMVCObjectDictionaryValueItem = class
function Add(const Name: string; const Value: TDataset;
const SerializationAction: TMVCDataSetSerializationAction = nil;
const DataSetSerializationType: TMVCDatasetSerializationType = dstAllRecords;
const NameCase: TMVCNameCase = TMVCNameCase.ncLowerCase;
const NameCase: TMVCNameCase = TMVCNameCase.ncUseDefault;
const AIgnoredFields: TMVCIgnoredList = nil): IMVCObjectDictionary; overload;
function TryGetValue(const Name: string; out Value: TObject): Boolean; overload;
function Count: Integer;
Expand Down Expand Up @@ -418,6 +419,9 @@ TMVCObjectDictionaryValueItem = class
/// </example>
gLocalTimeStampAsUTC: Boolean;

var
MVCNameCaseDefault: TMVCNameCase = TMVCNameCase.ncLowerCase;

function DateTimeToISOTimeStamp(const ADateTime: TDateTime): string;
function DateToISODate(const ADate: TDateTime): string;
function TimeToISOTime(const ATime: TTime): string;
Expand All @@ -439,7 +443,7 @@ function ISODateToDate(const ADate: string): TDate;
function ISOTimeToTime(const ATime: string): TTime;

const
JSONNameLowerCase = ncLowerCase deprecated 'Use MVCNameCaseAttribute(ncLowerCase)';
JSONNameLowerCase = TMVCNameCase.ncLowerCase deprecated 'Use MVCNameCaseAttribute(ncLowerCase)';
JSONNameUpperCase = ncUpperCase deprecated 'Use MVCNameCaseAttribute(ncUpperCase)';

function StrDict: TMVCStringDictionary; overload;
Expand Down Expand Up @@ -654,36 +658,41 @@ class function TMVCSerializerHelper.AttributeExists<T>(const AAttributes: TArray
Result := (AAttribute <> nil);
end;

class function TMVCSerializerHelper.ApplyNameCase(const NameCase: TMVCNameCase;
class function TMVCSerializerHelper.ApplyNameCase(NameCase: TMVCNameCase;
const Value: string): string;
begin
if NameCase = TMVCNameCase.ncUseDefault then
begin
NameCase := MVCNameCaseDefault;
end;

case NameCase of
ncUpperCase:
TMVCNameCase.ncUpperCase:
begin
Result := UpperCase(Value);
end;
ncLowerCase:
TMVCNameCase.ncLowerCase:
begin
Result := LowerCase(Value);
end;
ncCamelCase:
TMVCNameCase.ncCamelCase:
begin
Result := CamelCase(Value);
end;
ncPascalCase:
TMVCNameCase.ncPascalCase:
begin
Result := CamelCase(Value, True);
end;
ncSnakeCase:
TMVCNameCase.ncSnakeCase:
begin
Result := SnakeCase(Value);
end;
ncAsIs:
TMVCNameCase.ncAsIs:
begin
Result := Value;
end
else
raise Exception.Create('Invalid NameCase');
raise Exception.Create('Unknown TMVCNameCase: ' + GetEnumName(TypeInfo(TMVCNameCase), Ord(NameCase)));
end;
end;

Expand Down Expand Up @@ -829,14 +838,14 @@ class function TMVCSerializerHelper.GetKeyName(const AProperty: TRttiProperty;
end;
end;

Attrs := AType.GetAttributes;
for Attr in Attrs do
for Attr in AType.GetAttributes do
begin
if Attr is MVCNameCaseAttribute then
begin
Exit(TMVCSerializerHelper.ApplyNameCase(MVCNameCaseAttribute(Attr).KeyCase, Result));
end;
end;
Result := TMVCSerializerHelper.ApplyNameCase(MVCNameCaseDefault, Result);
end;

class function TMVCSerializerHelper.GetTypeKindAsString(const ATypeKind: TTypeKind): string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ procedure TMVCDataSetHolderSerializer.SerializeRoot(const AObject: TObject; out
try
if lDataSetHolder.SerializationType = TMVCDatasetSerializationType.dstAllRecords then
begin
lSer.DataSetToJsonArray(lDataSetHolder.Items, lOutObject.A['data'], TMVCNameCase.ncLowerCase, [])
lSer.DataSetToJsonArray(lDataSetHolder.Items, lOutObject.A['data'], TMVCNameCase.ncUseDefault, [])
end
else // single record
begin
Expand All @@ -426,9 +426,9 @@ procedure TMVCDataSetHolderSerializer.SerializeRoot(const AObject: TObject; out
raise EMVCException.CreateFmt('DataSet contains %d records - exactly 1 expected',
[lDataSetHolder.Items.RecordCount]);
end;
lDSFields := lSer.GetDataSetFields(lDataSetHolder.Items, [], TMVCNameCase.ncLowerCase);
lDSFields := lSer.GetDataSetFields(lDataSetHolder.Items, [], TMVCNameCase.ncUseDefault);
try
lSer.DataSetToJsonObject(lDataSetHolder.Items, lOutObject.O['data'], TMVCNameCase.ncLowerCase, [],
lSer.DataSetToJsonObject(lDataSetHolder.Items, lOutObject.O['data'], TMVCNameCase.ncUseDefault, [],
lDSFields);
finally
lDSFields.Free;
Expand Down
Loading

0 comments on commit 07e16a3

Please sign in to comment.