From 1b2a9231bfabf4746ef275306d215ea9656a8384 Mon Sep 17 00:00:00 2001 From: macgayver Date: Thu, 21 Jan 2021 10:24:27 -0300 Subject: [PATCH 1/2] Delphi, when converting objects to JSON, in the procedure "TJSONConverter.ConvertFieldNameToJson", it forcibly changes the first letter to lowercase, and there are Rest server implementations that are sensitive to the case of JSON keys. I imagine that Embarcadero did not take action on this because there is the [JSONName] attribute that tells the converter to use exactly as defined in the attribute. So I added an option in the application to add the JSONName attribute automatically. --- Pkg.Json.Mapper.pas | 9 +++++++-- uMainForm.fmx | 32 ++++++++++++++++++++++++++++---- uMainForm.pas | 4 ++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/Pkg.Json.Mapper.pas b/Pkg.Json.Mapper.pas index 641e6fc..e924af2 100644 --- a/Pkg.Json.Mapper.pas +++ b/Pkg.Json.Mapper.pas @@ -1,7 +1,7 @@ unit Pkg.Json.Mapper; interface -uses FMX.TreeView, System.JSON, Rest.Json, RTTI, RegularExpressions, TypInfo, +uses FMX.TreeView, System.JSON, System.StrUtils, Rest.Json, RTTI, RegularExpressions, TypInfo, SysUtils, classes, Generics.Collections, Generics.Defaults; type @@ -89,6 +89,7 @@ TPkgJsonMapper = class FClasses: TList; FRootClass: TStubClass; FUnitName: string; + FPreserveCapitalization: Boolean; procedure SetUnitName(const Value: string); protected function GetJsonType(AJsonValue: TJsonValue): TJsonType; @@ -110,6 +111,7 @@ TPkgJsonMapper = class // Visualizes stub class structure in a treeview procedure Visualize(ATreeView: TTreeView; AItemStyleLookup: string); property DestinationUnitName: string read FUnitName write SetUnitName; + property PreserveCapitalization: Boolean read FPreserveCapitalization write FPreserveCapitalization; end; procedure PrettyPrintJSON(JSONValue: TJSONValue; OutputStrings: TStrings; indent: integer = 0); @@ -267,7 +269,7 @@ function TPkgJsonMapper.GenerateUnit: string; LList.Add(''); LList.Add('interface'); LList.Add(''); - LList.Add('uses Generics.Collections, Rest.Json;'); + LList.Add('uses Generics.Collections, Rest.Json' + ifThen(FPreserveCapitalization,', Rest.Json.Types','') +';'); LList.Add(''); LList.Add('type'); @@ -755,6 +757,9 @@ LLines.Add(FName + ' = class'); if (LItem.FieldType = jtUnknown) OR ((LItem is TStubContainerField) AND ((LItem as TStubContainerField).ContainedType = jtUnknown)) then raise EJsonMapper.CreateFmt('The property [%s] has unknown type!', [LItem.PropertyName]); + if FMapper.PreserveCapitalization then + LLines.Add(format(' [JsonName(''%s'')]',[LItem.PropertyName])); + LString := format(' property %s: %s read %s write %s;', [LItem.PropertyName, LItem.GetTypeAsString, LItem.FieldName, LItem.FieldName]); LLines.Add(LString); end; diff --git a/uMainForm.fmx b/uMainForm.fmx index 72faef3..ae6ada5 100644 --- a/uMainForm.fmx +++ b/uMainForm.fmx @@ -1707,13 +1707,13 @@ object MainForm: TMainForm Margins.Bottom = 6.000000000000000000 PopupMenu = MemoPopupMenu Size.Width = 657.000000000000000000 - Size.Height = 448.000000000000000000 + Size.Height = 414.000000000000000000 Size.PlatformDefault = False StyleLookup = 'Memo1Style1' TabOrder = 0 OnDblClick = Memo1DblClick Viewport.Width = 637.000000000000000000 - Viewport.Height = 428.000000000000000000 + Viewport.Height = 394.000000000000000000 end object Panel3: TPanel Align = Bottom @@ -1722,11 +1722,11 @@ object MainForm: TMainForm Padding.Right = 6.000000000000000000 Padding.Bottom = 6.000000000000000000 Position.X = 6.000000000000000000 - Position.Y = 473.000000000000000000 + Position.Y = 439.000000000000000000 Size.Width = 657.000000000000000000 Size.Height = 53.000000000000000000 Size.PlatformDefault = False - TabOrder = 1 + TabOrder = 2 object btnVisualize: TButton Align = Right Margins.Right = 9.000000000000000000 @@ -1812,6 +1812,30 @@ object MainForm: TMainForm Size.PlatformDefault = False Text = 'Paste JSON String here:' end + object Panel5: TPanel + Align = Bottom + Padding.Left = 6.000000000000000000 + Padding.Top = 6.000000000000000000 + Padding.Right = 6.000000000000000000 + Padding.Bottom = 6.000000000000000000 + Margins.Top = 4.000000000000000000 + Position.X = 6.000000000000000000 + Position.Y = 496.000000000000000000 + Size.Width = 657.000000000000000000 + Size.Height = 30.000000000000000000 + Size.PlatformDefault = False + TabOrder = 1 + object CheckBox1: TCheckBox + Align = Left + Position.X = 6.000000000000000000 + Position.Y = 6.000000000000000000 + Size.Width = 307.000000000000000000 + Size.Height = 18.000000000000000000 + Size.PlatformDefault = False + TabOrder = 2 + Text = 'Preserve capitalization of words' + end + end end object Splitter1: TSplitter Align = Left diff --git a/uMainForm.pas b/uMainForm.pas index 4732427..b9c7094 100644 --- a/uMainForm.pas +++ b/uMainForm.pas @@ -44,6 +44,8 @@ TMainForm = class(TConstrainedForm) Panel4: TPanel; MenuItem8: TMenuItem; btnGenerateUnit: TButton; + Panel5: TPanel; + CheckBox1: TCheckBox; procedure btnVisualizeClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); @@ -138,6 +140,8 @@ procedure TMainForm.DisableMenuItems; procedure TMainForm.PreviewUnitClick(Sender: TObject); begin + jm.PreserveCapitalization := CheckBox1.IsChecked; + if tv.Count = 0 then btnVisualizeClick(self); From a156d783735306f64fd99acf6bbfb8b2bb147cab Mon Sep 17 00:00:00 2001 From: macgayver Date: Thu, 21 Jan 2021 10:44:00 -0300 Subject: [PATCH 2/2] Correction of Attribute position --- Pkg.Json.Mapper.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Pkg.Json.Mapper.pas b/Pkg.Json.Mapper.pas index e924af2..b72af79 100644 --- a/Pkg.Json.Mapper.pas +++ b/Pkg.Json.Mapper.pas @@ -746,6 +746,9 @@ LLines.Add(FName + ' = class'); for LItem in FItems do begin + if FMapper.PreserveCapitalization then + LLines.Add(format(' [JsonName(''%s'')]',[LItem.PropertyName])); + LString := format(' %s: %s;', [LItem.FieldName, LItem.GetTypeAsString]); LLines.Add(LString); end; @@ -757,9 +760,6 @@ LLines.Add(FName + ' = class'); if (LItem.FieldType = jtUnknown) OR ((LItem is TStubContainerField) AND ((LItem as TStubContainerField).ContainedType = jtUnknown)) then raise EJsonMapper.CreateFmt('The property [%s] has unknown type!', [LItem.PropertyName]); - if FMapper.PreserveCapitalization then - LLines.Add(format(' [JsonName(''%s'')]',[LItem.PropertyName])); - LString := format(' property %s: %s read %s write %s;', [LItem.PropertyName, LItem.GetTypeAsString, LItem.FieldName, LItem.FieldName]); LLines.Add(LString); end;