Skip to content

Commit

Permalink
Merge pull request #437 from joaoduarte19/serialize_snake_case
Browse files Browse the repository at this point in the history
MVCNameCase improvements
  • Loading branch information
danieleteti committed Oct 17, 2020
2 parents 40417c8 + 46f28cd commit 55f6a7d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 15 deletions.
34 changes: 29 additions & 5 deletions sources/MVCFramework.Commons.pas
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,8 @@ implementation
IdCoder3to4,
System.NetEncoding,
System.Character,
MVCFramework.Serializer.JsonDataObjects, MVCFramework.Serializer.Commons;
MVCFramework.Serializer.JsonDataObjects, MVCFramework.Serializer.Commons,
System.RegularExpressions;

var
GlobalAppName, GlobalAppPath, GlobalAppExe: string;
Expand Down Expand Up @@ -1392,6 +1393,7 @@ function CamelCase(const Value: string; const MakeFirstUpperToo: Boolean): strin
lIsLowerCase: Boolean;
lIsUpperCase, lPreviousWasUpperCase: Boolean;
lIsAlpha: Boolean;
lIsNumber: Boolean;
begin
{TODO -oDanieleT -cGeneral : Make this function faster!}
lNextUpCase := MakeFirstUpperToo;
Expand All @@ -1403,8 +1405,9 @@ function CamelCase(const Value: string; const MakeFirstUpperToo: Boolean): strin
C := Value.Chars[I];
lIsLowerCase := CharInSet(C, ['a' .. 'z']);
lIsUpperCase := CharInSet(C, ['A' .. 'Z']);
lIsNumber := CharInSet(C, ['0' .. '9']);
lIsAlpha := lIsLowerCase or lIsUpperCase;
if not lIsAlpha then
if not (lIsAlpha or lIsNumber) then
begin
lNextUpCase := True;
lPreviousWasUpperCase := False;
Expand All @@ -1430,6 +1433,10 @@ function CamelCase(const Value: string; const MakeFirstUpperToo: Boolean): strin
end;
end;
lPreviousWasUpperCase := lIsUpperCase;
if lIsNumber then
begin
lNextUpCase := True;
end;
end;
Result := lSB.ToString;
finally
Expand All @@ -1444,18 +1451,30 @@ function SnakeCase(const Value: string): string;
C: Char;
lIsUpperCase, lIsLowerCase, lLastWasLowercase: Boolean;
lCanInsertAnUnderscore: Boolean;
lIsNumber: Boolean;
lLastWasUnderscore: Boolean;
lIsUnderscore: Boolean;
lLastWasNumber: Boolean;
lIsAlpha: Boolean;
begin
lCanInsertAnUnderscore := False;
lLastWasLowercase := False;
lLastWasUnderscore := False;
lLastWasNumber := False;
lSB := TStringBuilder.Create;
try
for I := 0 to Length(Value) - 1 do
begin
C := Value.Chars[I];
lIsUpperCase := CharInSet(C, ['A' .. 'Z']);
lIsLowerCase := CharInSet(C, ['a' .. 'z']);
lCanInsertAnUnderscore := lCanInsertAnUnderscore and lLastWasLowercase;
if lIsUpperCase and (I > 0) and lCanInsertAnUnderscore then
lIsNumber := CharInSet(C, ['0' .. '9']);
lIsUnderscore := C = '_';
lIsAlpha := lIsUpperCase or lIsLowerCase;

lCanInsertAnUnderscore := lCanInsertAnUnderscore and (lLastWasLowercase or lLastWasNumber) and
(not lLastWasUnderscore);
if (lIsUpperCase or lIsNumber or (lIsAlpha and lLastWasNumber)) and (I > 0) and lCanInsertAnUnderscore then
begin
lSB.Append('_');
lCanInsertAnUnderscore := False;
Expand All @@ -1464,8 +1483,13 @@ function SnakeCase(const Value: string): string;
begin
lCanInsertAnUnderscore := True;
end;
lSB.Append(LowerCase(C));
if not (lLastWasUnderscore and lIsUnderscore) then
begin
lSB.Append(LowerCase(C));
end;
lLastWasUnderscore := lIsUnderscore;
lLastWasLowercase := lIsLowerCase;
lLastWasNumber := lIsNumber;
end;
Result := lSB.ToString;
finally
Expand Down
6 changes: 5 additions & 1 deletion sources/MVCFramework.Serializer.Commons.pas
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ EMVCDeserializationException = class(EMVCException)

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

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

TMVCDataType = (dtObject, dtArray);

Expand Down Expand Up @@ -627,6 +627,10 @@ class function TMVCSerializerHelper.ApplyNameCase(const NameCase: TMVCNameCase;
begin
Result := CamelCase(Value, True);
end;
ncSnakeCase:
begin
Result := SnakeCase(Value);
end;
ncAsIs:
begin
Result := Value;
Expand Down
31 changes: 22 additions & 9 deletions unittests/general/Several/FrameworkTestsU.pas
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ TTestMultiMap = class(TObject)
[TestFixture]
TTestNameCase = class(TObject)
private
fOutDATA: array [1 .. 4] of array [ncAsIs .. ncPascalCase] of string;
fOrigDATA: array [1 .. 4] of string;
fOutDATA: array [1 .. 5] of array [ncAsIs .. ncSnakeCase] of string;
fOrigDATA: array [1 .. 5] of string;
public
[SetupFixture]
procedure SetupFixture;
Expand Down Expand Up @@ -1790,35 +1790,48 @@ procedure TTestMultiMap.TestObjectMultiMapRemove;

procedure TTestNameCase.SetupFixture;
begin
fOrigDATA[1] := 'one_two';
fOrigDATA[1] := 'one_two_3or4';
fOrigDATA[2] := 'ONE_TWO_THREE';
fOrigDATA[3] := 'JustOne';
fOrigDATA[4] := '_with__underscores_';
fOrigDATA[5] := 'oneTwo___three04';

fOutDATA[1][ncAsIs] := fOrigDATA[1];
fOutDATA[2][ncAsIs] := fOrigDATA[2];
fOutDATA[3][ncAsIs] := fOrigDATA[3];
fOutDATA[4][ncAsIs] := fOrigDATA[4];
fOutDATA[5][ncAsIs] := fOrigDATA[5];

fOutDATA[1][ncUpperCase] := 'ONE_TWO';
fOutDATA[1][ncUpperCase] := 'ONE_TWO_3OR4';
fOutDATA[2][ncUpperCase] := 'ONE_TWO_THREE';
fOutDATA[3][ncUpperCase] := 'JUSTONE';
fOutDATA[4][ncUpperCase] := '_WITH__UNDERSCORES_';
fOutDATA[5][ncUpperCase] := 'ONETWO___THREE04';

fOutDATA[1][ncLowerCase] := 'one_two';
fOutDATA[1][ncLowerCase] := 'one_two_3or4';
fOutDATA[2][ncLowerCase] := 'one_two_three';
fOutDATA[3][ncLowerCase] := 'justone';
fOutDATA[4][ncLowerCase] := '_with__underscores_';
fOutDATA[5][ncLowerCase] := 'onetwo___three04';

fOutDATA[1][ncCamelCase] := 'oneTwo';
fOutDATA[1][ncCamelCase] := 'oneTwo3Or4';
fOutDATA[2][ncCamelCase] := 'oneTwoThree';
fOutDATA[3][ncCamelCase] := 'justOne';
fOutDATA[4][ncCamelCase] := 'WithUnderscores';
fOutDATA[5][ncCamelCase] := 'oneTwoThree04';

fOutDATA[1][ncPascalCase] := 'OneTwo';
fOutDATA[1][ncPascalCase] := 'OneTwo3Or4';
fOutDATA[2][ncPascalCase] := 'OneTwoThree';
fOutDATA[3][ncPascalCase] := 'JustOne';
fOutDATA[4][ncPascalCase] := 'WithUnderscores';
fOutDATA[5][ncPascalCase] := 'OneTwoThree04';

fOutDATA[1][ncSnakeCase] := 'one_two_3_or_4';
fOutDATA[2][ncSnakeCase] := 'one_two_three';
fOutDATA[3][ncSnakeCase] := 'just_one';
fOutDATA[4][ncSnakeCase] := '_with_underscores_';
fOutDATA[5][ncSnakeCase] := 'one_two_three_04';

end;

procedure TTestNameCase.TestNameCase;
Expand All @@ -1829,9 +1842,9 @@ procedure TTestNameCase.TestNameCase;
lOutData: string;
lActualOutData: string;
begin
for lNameCaseIdx := ncAsIs to ncPascalCase do
for lNameCaseIdx := ncAsIs to ncSnakeCase do
begin
for I := 1 to 4 do
for I := 1 to 5 do
begin
lOrig := fOrigDATA[I];
lOutData := fOutDATA[I][lNameCaseIdx];
Expand Down

0 comments on commit 55f6a7d

Please sign in to comment.