浏览代码

Merge branch 'develop'

Unknown 7 年之前
父节点
当前提交
852c05bacf

+ 234 - 0
Quick.AutoMapper.pas

@@ -0,0 +1,234 @@
+{ ***************************************************************************
+
+  Copyright (c) 2015-2018 Kike Pérez
+
+  Unit        : Quick.AutoMapper
+  Description : Auto Mapper object properties
+  Author      : Kike Pérez
+  Version     : 1.0
+  Created     : 25/08/2018
+  Modified    : 30/08/2018
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+
+unit Quick.AutoMapper;
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  {$IFDEF FPC}
+  typinfo,
+  {$ENDIF}
+  RTTI;
+
+type
+
+  TCustomMapping = class
+  private
+    fMapDictionary : TDictionary<string,string>;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    procedure AddMap(const aName, aMapName : string);
+    function GetMap(const aName : string; out vMapName : string) : Boolean;
+  end;
+
+  TObjMapper = class
+  public
+    class procedure Map(aSrcObj : TObject; aTgtObj : TObject; aCustomMapping: TCustomMapping = nil);
+  end;
+
+  TMapper<T : class, constructor> = class
+  public
+    class function Map(aSrcObj : TObject; aCustomMapping: TCustomMapping = nil): T; overload;
+    class procedure Map(aSrcObj : TObject; aTgtObj : T; aCustomMapping : TCustomMapping = nil); overload;
+  end;
+
+  TAutoMapper<TClass1, TClass2 : class, constructor> = class
+  private
+    fCustomMapping : TCustomMapping;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    property CustomMapping : TCustomMapping read fCustomMapping write fCustomMapping;
+    function Map(aSrcObj : TClass1) : TClass2; overload;
+    {$IFNDEF FPC}
+    function Map(aSrcObj : TClass2) : TClass1; overload;
+    {$ELSE}
+    //freepascal detects overload with generic types as duplicated function, added dummy field to avoid this
+    function Map(aSrcObj : TClass2; dummy : Boolean = True) : TClass1; overload;
+    {$ENDIF}
+  end;
+
+  EAutoMapperError = class(Exception);
+
+implementation
+
+{ TObjMapper }
+
+class procedure TObjMapper.Map(aSrcObj : TObject; aTgtObj : TObject; aCustomMapping: TCustomMapping = nil);
+var
+  ctx : TRttiContext;
+  rType : TRttiType;
+  tgtprop : TRttiProperty;
+  mapname : string;
+  obj : TObject;
+begin
+  if aTgtObj = nil then aTgtObj := aTgtObj.ClassType.Create;
+
+  for tgtprop in ctx.GetType(aTgtObj.ClassInfo).GetProperties do
+  begin
+    if tgtprop.IsWritable then
+    begin
+      if not tgtprop.PropertyType.IsInstance then
+      begin
+        rType := ctx.GetType(aSrcObj.ClassInfo);
+        if Assigned(aCustomMapping) then
+        begin
+          if aCustomMapping.GetMap(tgtprop.Name,mapname) then
+          begin
+            if rType.GetProperty(mapname) = nil then raise EAutoMapperError.CreateFmt('No valid custom mapping (Source: %s - Target: %s)',[mapname,tgtprop.Name]);
+            {$IFNDEF FPC}
+            tgtprop.SetValue(aTgtObj,rType.GetProperty(mapname).GetValue(aSrcObj))
+            {$ELSE}
+            SetPropValue(aTgtObj,tgtprop.Name,GetPropValue(aSrcObj,mapname));
+            {$ENDIF}
+          end
+          else
+          begin
+            if rType.GetProperty(tgtprop.Name) <> nil then
+            try
+              {$IFNDEF FPC}
+              tgtprop.SetValue(aTgtObj,rType.GetProperty(tgtprop.Name).GetValue(aSrcObj));
+              {$ELSE}
+              SetPropValue(aTgtObj,tgtprop.Name,GetPropValue(aSrcObj,tgtprop.Name));
+              {$ENDIF}
+            except
+              on E : Exception do raise EAUtoMapperError.CreateFmt('Error mapping property "%s" : %s',[tgtprop.Name,e.message]);
+            end;
+          end;
+        end
+        else
+        begin
+          try
+            {$IFNDEF FPC}
+            if rType.GetProperty(tgtprop.Name) <> nil then tgtprop.SetValue(aTgtObj,rType.GetProperty(tgtprop.Name).GetValue(aSrcObj));
+            {$ELSE}
+            if rType.GetProperty(tgtprop.Name) <> nil then SetPropValue(aTgtObj,tgtprop.Name,GetPropValue(aSrcObj,tgtprop.Name));
+            {$ENDIF}
+          except
+            on E : Exception do raise EAUtoMapperError.CreateFmt('Error mapping property "%s" : %s',[tgtprop.Name,e.message]);
+          end;
+        end;
+      end
+      else
+      begin
+        obj := tgtprop.GetValue(aTgtObj).AsObject;
+        {$IFNDEF FPC}
+        if obj = nil then obj := TObject.Create;
+        {$ELSE}
+        if obj = nil then obj := GetObjectProp(aSrcObj,tgtprop.Name).ClassType.Create;
+        {$ENDIF}
+
+        if obj <> nil then
+        begin
+          {$IFNDEF FPC}
+          TObjMapper.Map(rType.GetProperty(tgtprop.Name).GetValue(aSrcObj).AsObject,obj,aCustomMapping);
+          {$ELSE}
+          TObjMapper.Map(GetObjectProp(aSrcObj,tgtprop.Name),obj,aCustomMapping);
+          SetObjectProp(aTgtObj,tgtprop.Name,obj);
+          {$ENDIF}
+        end
+        else raise EAutoMapperError.CreateFmt('Target object "%s" not autocreated by class',[tgtprop.Name]);
+      end;
+    end;
+  end;
+end;
+
+class function TMapper<T>.Map(aSrcObj : TObject; aCustomMapping: TCustomMapping = nil) : T;
+var
+  obj : T;
+begin
+  obj := T.Create;
+  TObjMapper.Map(aSrcObj,obj,aCustomMapping);
+  Result := obj;
+end;
+
+class procedure TMapper<T>.Map(aSrcObj : TObject; aTgtObj : T; aCustomMapping : TCustomMapping = nil);
+begin
+  TObjMapper.Map(aSrcObj, aTgtObj, aCustomMapping);
+end;
+
+{ TAutoMapper<TClass1, TClass2> }
+
+constructor TAutoMapper<TClass1, TClass2>.Create;
+begin
+  fCustomMapping := TCustomMapping.Create;
+end;
+
+destructor TAutoMapper<TClass1, TClass2>.Destroy;
+begin
+  if Assigned(fCustomMapping) then fCustomMapping.Free;
+  inherited;
+end;
+
+{}
+function TAutoMapper<TClass1, TClass2>.Map(aSrcObj: TClass1): TClass2;
+begin
+  Result := TMapper<TClass2>.Map(aSrcObj,fCustomMapping);
+end;
+
+{$IFNDEF FPC}
+function TAutoMapper<TClass1, TClass2>.Map(aSrcObj: TClass2): TClass1;
+{$ELSE}
+function TAutoMapper<TClass1, TClass2>.Map(aSrcObj: TClass2; dummy : Boolean = True): TClass1;
+{$ENDIF}
+begin
+  Result := TMapper<TClass1>.Map(aSrcObj,fCustomMapping);
+end;
+
+{ TCustomMappingFields }
+
+procedure TCustomMapping.AddMap(const aName, aMapName: string);
+begin
+  //add map fields
+  fMapDictionary.Add(aName,aMapName);
+  //add reverse lookup
+  fMapDictionary.Add(aMapName,aName);
+end;
+
+constructor TCustomMapping.Create;
+begin
+  fMapDictionary := TDictionary<string,string>.Create;
+end;
+
+destructor TCustomMapping.Destroy;
+begin
+  fMapDictionary.Free;
+  inherited;
+end;
+
+function TCustomMapping.GetMap(const aName: string; out vMapName: string): Boolean;
+begin
+  Result := fMapDictionary.TryGetValue(aName,vMapName);
+end;
+
+end.

+ 17 - 4
Quick.Base64.pas

@@ -3,11 +3,11 @@
   Copyright (c) 2016-2017 Kike Pérez
   Copyright (c) 2016-2017 Kike Pérez
 
 
   Unit        : Quick.Base64
   Unit        : Quick.Base64
-  Description : Log Api Redis Provider
+  Description : Base64 functions
   Author      : Kike Pérez
   Author      : Kike Pérez
   Version     : 1.1
   Version     : 1.1
   Created     : 08/11/2017
   Created     : 08/11/2017
-  Modified    : 07/05/2018
+  Modified    : 14/08/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -28,13 +28,17 @@
  *************************************************************************** }
  *************************************************************************** }
 unit Quick.Base64;
 unit Quick.Base64;
 
 
-interface
-
 {$i QuickLib.inc}
 {$i QuickLib.inc}
 
 
+interface
+
 uses
 uses
+  {$IFDEF DELPHIXE7_UP}
+  System.NetEncoding;
+  {$ELSE}
   IdCoderMIME,
   IdCoderMIME,
   IdGlobal;
   IdGlobal;
+  {$ENDIF}
 
 
 function Base64Encode(const Input: string): string;
 function Base64Encode(const Input: string): string;
 function Base64Decode(const Input: string): string;
 function Base64Decode(const Input: string): string;
@@ -43,12 +47,21 @@ implementation
 
 
 function Base64Encode(const Input: string): string;
 function Base64Encode(const Input: string): string;
 begin
 begin
+  {$IFDEF DELPHIXE7_UP}
+  Result := TNetEncoding.Base64.Encode(Input);
+  {$ELSE}
   Result := TIdEncoderMIME.EncodeString(Input,IndyTextEncoding_OSDefault);
   Result := TIdEncoderMIME.EncodeString(Input,IndyTextEncoding_OSDefault);
+  {$ENDIF}
 end;
 end;
 
 
 function Base64Decode(const Input: string): string;
 function Base64Decode(const Input: string): string;
 begin
 begin
+  {$IFDEF DELPHIXE7_UP}
+  Result := TNetEncoding.Base64.Decode(Input);
+  {$ELSE}
   Result := TIdDecoderMIME.DecodeString(Input,IndyTextEncoding_OSDefault);
   Result := TIdDecoderMIME.DecodeString(Input,IndyTextEncoding_OSDefault);
+  {$ENDIF}
 end;
 end;
 
 
 end.
 end.
+

+ 81 - 51
Quick.Commons.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.Commons
   Unit        : Quick.Commons
   Description : Common functions
   Description : Common functions
   Author      : Kike Pérez
   Author      : Kike Pérez
-  Version     : 1.4
+  Version     : 1.5
   Created     : 14/07/2017
   Created     : 14/07/2017
-  Modified    : 16/05/2018
+  Modified    : 13/08/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -50,6 +50,12 @@ interface
     {$ELSE}
     {$ELSE}
     IOUtils,
     IOUtils,
     {$ENDIF}
     {$ENDIF}
+    {$IFDEF ANDROID}
+    Androidapi.JNI.Os,
+    Androidapi.Helpers,
+    Androidapi.JNI.JavaTypes,
+    Androidapi.JNI.GraphicsContentViewText,
+    {$ENDIF}
     DateUtils;
     DateUtils;
 
 
 type
 type
@@ -641,42 +647,50 @@ end;
 
 
 function GetLoggedUserName : string;
 function GetLoggedUserName : string;
 {$IFDEF MSWINDOWS}
 {$IFDEF MSWINDOWS}
-const
-  cnMaxUserNameLen = 254;
-var
-  sUserName     : string;
-  dwUserNameLen : DWord;
-begin
-  dwUserNameLen := cnMaxUserNameLen-1;
-  SetLength( sUserName, cnMaxUserNameLen );
-  GetUserName(PChar( sUserName ),dwUserNameLen );
-  SetLength( sUserName, dwUserNameLen );
-  Result := sUserName;
-end;
-{$ENDIF}
-{$IF DEFINED(FPC) AND DEFINED(LINUX)}
-begin
-  Result := GetEnvironmentVariable('USERNAME');
-end;
-
+  const
+    cnMaxUserNameLen = 254;
+  var
+    sUserName     : string;
+    dwUserNameLen : DWord;
+  begin
+    dwUserNameLen := cnMaxUserNameLen-1;
+    SetLength( sUserName, cnMaxUserNameLen );
+    GetUserName(PChar( sUserName ),dwUserNameLen );
+    SetLength( sUserName, dwUserNameLen );
+    Result := sUserName;
+  end;
+{$ELSE}
+  {$IF DEFINED(FPC) AND DEFINED(LINUX)}
+  begin
+    Result := GetEnvironmentVariable('USERNAME');
+  end;
+  {$ELSE}
+  begin
+    raise ENotImplemented.Create('Not Android GetLoggedUserName implemented!');
+  end;
+  {$ENDIF}
 {$ENDIF}
 {$ENDIF}
 
 
 function GetComputerName : string;
 function GetComputerName : string;
 {$IFDEF MSWINDOWS}
 {$IFDEF MSWINDOWS}
-var
-  dwLength: dword;
-begin
-  dwLength := 253;
-  SetLength(Result, dwLength+1);
-  if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
-  Result := pchar(result);
-end;
-{$ENDIF}
-{$IF DEFINED(FPC) AND DEFINED(LINUX)}
-begin
-  Result := GetEnvironmentVariable('COMPUTERNAME');
-end;
-
+  var
+    dwLength: dword;
+  begin
+    dwLength := 253;
+    SetLength(Result, dwLength+1);
+    if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
+    Result := pchar(result);
+  end;
+{$ELSE}
+  {$IF DEFINED(FPC) AND DEFINED(LINUX)}
+  begin
+    Result := GetEnvironmentVariable('COMPUTERNAME');
+  end;
+  {$ELSE} //Android gets model name
+  begin
+    Result := JStringToString(TJBuild.JavaClass.MODEL);
+  end;
+  {$ENDIF}
 {$ENDIF}
 {$ENDIF}
 
 
 function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
 function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
@@ -790,14 +804,22 @@ begin
   end
   end
   else Result := '';
   else Result := '';
 end;
 end;
-{$ENDIF}
-{$IF DEFINED(FPC) AND DEFINED(LINUX)}
-var
-  version : TProgramVersion;
-begin
-  if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
-    else Result := '';
-end;
+{$ELSE}
+  {$IF DEFINED(FPC) AND DEFINED(LINUX)}
+  var
+    version : TProgramVersion;
+  begin
+    if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
+      else Result := '';
+  end;
+  {$ELSE}
+  var
+    PkgInfo : JPackageInfo;
+  begin
+    PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
+    Result := IntToStr(PkgInfo.VersionCode);
+  end;
+  {$ENDIF}
 {$ENDIF}
 {$ENDIF}
 
 
 function GetAppVersionFullStr: string;
 function GetAppVersionFullStr: string;
@@ -844,14 +866,22 @@ begin
      LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
      LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
   end;
   end;
 end;
 end;
-{$ENDIF}
-{$IF DEFINED(FPC) AND DEFINED(LINUX)}
-var
-  version : TProgramVersion;
-begin
-  if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
-    else Result := '';
-end;
+{$ELSE}
+  {$IF DEFINED(FPC) AND DEFINED(LINUX)}
+  var
+    version : TProgramVersion;
+  begin
+    if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
+      else Result := '';
+  end;
+  {$ELSE}
+  var
+    PkgInfo : JPackageInfo;
+  begin
+    PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
+    Result := JStringToString(PkgInfo.versionName);
+  end;
+  {$ENDIF}
 {$ENDIF}
 {$ENDIF}
 
 
 function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
 function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
@@ -1037,8 +1067,8 @@ begin
 end;
 end;
 {$ENDIF}
 {$ENDIF}
 
 
-initialization
 {$IFDEF MSWINDOWS}
 {$IFDEF MSWINDOWS}
+initialization
   try
   try
     GetEnvironmentPaths;
     GetEnvironmentPaths;
   except
   except

+ 85 - 0
Quick.Compression.pas

@@ -0,0 +1,85 @@
+{ ***************************************************************************
+
+  Copyright (c) 2016-2017 Kike Pérez
+
+  Unit        : Quick.Compression
+  Description : Compression functions
+  Author      : Kike Pérez
+  Version     : 1.1
+  Created     : 14/08/2018
+  Modified    : 20/08/2018
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+unit Quick.Compression;
+
+{$i QuickLib.inc}
+
+interface
+
+uses
+  Classes,
+  System.SysUtils,
+  System.ZLib;
+
+  function CompressString(const aStr : string) : string;
+  function DecompressString(const aStr: string) : string;
+
+implementation
+
+function CompressString(const aStr : string) : string;
+var
+  strstream : TStringStream;
+  zipstream : TStringStream;
+begin
+  strstream := TStringStream.Create(aStr,TEncoding.UTF8);
+  try
+    zipstream := TStringStream.Create('',TEncoding.ANSI);
+    try
+      ZCompressStream(strstream, zipstream);
+      zipstream.Position := 0;
+      Result := zipstream.DataString;
+    finally
+      zipstream.Free;
+    end;
+  finally
+    strstream.Free;
+  end;
+end;
+
+function DecompressString(const aStr: string) : string;
+var
+  strstream : TStringStream;
+  zipstream : TStringStream;
+begin
+  zipstream := TStringStream.Create(aStr,TEncoding.ANSI);
+  try
+    strstream := TStringStream.Create('',TEncoding.UTF8);
+    try
+      ZDecompressStream(zipstream, strstream);
+      strstream.Position := 0;
+      Result := strstream.DataString;
+    finally
+      strstream.Free;
+    end;
+  finally
+    zipstream.Free;
+  end;
+end;
+
+end.

+ 10 - 4
Quick.Format.pas

@@ -7,7 +7,7 @@
   Author      : Kike Pérez
   Author      : Kike Pérez
   Version     : 1.4
   Version     : 1.4
   Created     : 14/07/2017
   Created     : 14/07/2017
-  Modified    : 07/04/2018
+  Modified    : 19/07/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -60,12 +60,18 @@ const
 var
 var
   i : Integer;
   i : Integer;
   bfmt : string;
   bfmt : string;
+  cspace : Char;
 begin
 begin
   i := 0;
   i := 0;
   while aBytes > Power(1024, i + 1) do Inc(i);
   while aBytes > Power(1024, i + 1) do Inc(i);
-  if Spaced then bfmt := '%.2f %s'
-    else bfmt := '%.2f%s';
-  Result := Format(bfmt,[aBytes / IntPower(1024, i),mesure[i]]);
+  if Spaced then cspace := Char(32)
+    else cspace := Char(0);
+    // bfmt := '%.2f %s'
+    //else bfmt := '%.2f%s';
+  if i < 2 then bfmt := '%.0f%s%s'
+    else bfmt := '%.2f%s%s';
+
+  Result := Format(bfmt,[aBytes / IntPower(1024, i),cspace,mesure[i]]);
 end;
 end;
 
 
 
 

+ 32 - 15
Quick.JSONRecord.pas

@@ -5,9 +5,9 @@
   Unit        : Quick.JSONRecord
   Unit        : Quick.JSONRecord
   Description : Serializable class
   Description : Serializable class
   Author      : Kike Pérez
   Author      : Kike Pérez
-  Version     : 1.0
+  Version     : 1.1
   Created     : 05/05/2018
   Created     : 05/05/2018
-  Modified    : 08/07/2018
+  Modified    : 28/08/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -34,7 +34,7 @@ interface
 
 
 uses
 uses
   Quick.Json.Serializer,
   Quick.Json.Serializer,
-  Rest.Json.Types;
+  Quick.AutoMapper;
 
 
 type
 type
 
 
@@ -42,12 +42,19 @@ type
   ['{AF71F59C-89A5-4BFB-8227-0CC3068B7671}']
   ['{AF71F59C-89A5-4BFB-8227-0CC3068B7671}']
     procedure FromJson(const aJson : string);
     procedure FromJson(const aJson : string);
     function ToJson : string;
     function ToJson : string;
+    procedure MapTo(aTgtObj : TObject);
+    procedure MapFrom(aSrcObj : TObject);
   end;
   end;
 
 
   TJsonRecord = class(TInterfacedObject,IJsonable)
   TJsonRecord = class(TInterfacedObject,IJsonable)
+  public
     constructor CreateFromJson(const aJson : string);
     constructor CreateFromJson(const aJson : string);
     procedure FromJson(const aJson : string);
     procedure FromJson(const aJson : string);
     function ToJson : string;
     function ToJson : string;
+    function Map<T : class, constructor> : T;
+    procedure MapTo(aTgtObj : TObject);
+    procedure MapFrom(aSrcObj : TObject);
+    function Clone : TObject; virtual;
   end;
   end;
 
 
 implementation
 implementation
@@ -58,11 +65,8 @@ constructor TJsonRecord.CreateFromJson(const aJson: string);
 var
 var
   serializer : TJsonSerializer;
   serializer : TJsonSerializer;
 begin
 begin
-  {$IFNDEF FPC}
+  //inherited Create;
   serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
   serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
-  {$ELSE}
-  serializer := TJsonSerializer.Create;
-  {$ENDIF}
   try
   try
     serializer.JsonToObject(Self,aJson);
     serializer.JsonToObject(Self,aJson);
   finally
   finally
@@ -74,11 +78,7 @@ procedure TJsonRecord.FromJson(const aJson: string);
 var
 var
   serializer : TJsonSerializer;
   serializer : TJsonSerializer;
 begin
 begin
-  {$IFNDEF FPC}
   serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
   serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
-  {$ELSE}
-  serializer := TJsonSerializer.Create;
-  {$ENDIF}
   try
   try
     serializer.JsonToObject(Self,aJson);
     serializer.JsonToObject(Self,aJson);
   finally
   finally
@@ -86,15 +86,26 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TJsonRecord.Map<T> : T;
+begin
+  Result := TMapper<T>.Map(Self);
+end;
+
+procedure TJsonRecord.MapFrom(aSrcObj: TObject);
+begin
+  TObjMapper.Map(aSrcObj,Self);
+end;
+
+procedure TJsonRecord.MapTo(aTgtObj: TObject);
+begin
+  TObjMapper.Map(Self,aTgtObj);
+end;
+
 function TJsonRecord.ToJson: string;
 function TJsonRecord.ToJson: string;
 var
 var
   serializer : TJsonSerializer;
   serializer : TJsonSerializer;
 begin
 begin
-  {$IFNDEF FPC}
   serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
   serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
-  {$ELSE}
-  serializer := TJsonSerializer.Create;
-  {$ENDIF}
   try
   try
     Result := serializer.ObjectToJson(Self);
     Result := serializer.ObjectToJson(Self);
   finally
   finally
@@ -102,4 +113,10 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TJsonRecord.Clone : TObject;
+begin
+  Result := Self.ClassType.Create;
+  TObjMapper.Map(Self,Result);
+end;
+
 end.
 end.

+ 13 - 4
Quick.Json.Serializer.pas

@@ -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    : 08/07/2018
+  Modified    : 28/08/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -379,6 +379,9 @@ end;
 
 
 constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel);
 constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel);
 begin
 begin
+  {$IFDEF FPC}
+  if aSerializeLevel = TSerializeLevel.slPublicProperty then raise EJsonSerializeError.Create('FreePascal RTTI only supports published properties');
+  {$ENDIF}
   fSerializeLevel := aSerializeLevel;
   fSerializeLevel := aSerializeLevel;
 end;
 end;
 
 
@@ -587,7 +590,9 @@ begin
       else
       else
         begin
         begin
           {$IFNDEF FPC}
           {$IFNDEF FPC}
-          rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
+          //avoid return unicode escaped chars if string
+          if aProperty.PropertyType.TypeKind in [tkString, tkLString, tkWString, tkUString] then rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.JsonString.ToString)
+            else rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
           {$ELSE}
           {$ELSE}
           rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
           rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
           if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
           if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
@@ -791,11 +796,13 @@ begin
     tkFloat : Result := GetFloatProp(Instance,PropertyName);
     tkFloat : Result := GetFloatProp(Instance,PropertyName);
     tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
     tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
     {$IFDEF FPC}
     {$IFDEF FPC}
+    tkWString : Result := GetWideStrProp(Instance,PropertyName);
     tkSString,
     tkSString,
     tkAString,
     tkAString,
+    {$ELSE}
+    tkWString,
     {$ENDIF}
     {$ENDIF}
     tkLString : Result := GetStrProp(Instance,pinfo);
     tkLString : Result := GetStrProp(Instance,pinfo);
-    tkWString : Result := GetWideStrProp(Instance,PropertyName);
     {$IFDEF FPC}
     {$IFDEF FPC}
     tkEnumeration : Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName));
     tkEnumeration : Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName));
     {$ELSE}
     {$ELSE}
@@ -828,11 +835,13 @@ begin
     tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
     tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
     tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
     tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
     {$IFDEF FPC}
     {$IFDEF FPC}
+    tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
     tkSString,
     tkSString,
     tkAString,
     tkAString,
+    {$ELSE}
+    tkWString,
     {$ENDIF}
     {$ENDIF}
     tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
     tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
-    tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
     {$IFDEF FPC}
     {$IFDEF FPC}
     tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
     tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
     tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
     tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);

+ 2 - 2
Quick.Json.fpc.Compatibility.pas

@@ -24,7 +24,7 @@ type
 
 
   { TJsonArray }
   { TJsonArray }
 
 
-  TJsonArrayEx = class(fpjson.TJSONArray)
+  TJsonArray = class(fpjson.TJSONArray)
   public
   public
     procedure AddElement(aValue : TJsonData);
     procedure AddElement(aValue : TJsonData);
   end;
   end;
@@ -65,7 +65,7 @@ implementation
 
 
 { TJsonArray }
 { TJsonArray }
 
 
-procedure TJsonArrayEx.AddElement(aValue: TJsonData);
+procedure TJsonArray.AddElement(aValue: TJsonData);
 begin
 begin
   Add(aValue);
   Add(aValue);
 end;
 end;

+ 2 - 2
Quick.Service.pas

@@ -7,7 +7,7 @@
   Author      : Kike Pérez
   Author      : Kike Pérez
   Version     : 1.1
   Version     : 1.1
   Created     : 14/07/2017
   Created     : 14/07/2017
-  Modified    : 07/04/2018
+  Modified    : 30/08/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -147,7 +147,7 @@ begin
         begin
         begin
           if QueryServiceStatus(svcHnd,svcStatus) then
           if QueryServiceStatus(svcHnd,svcStatus) then
           begin
           begin
-            while svcStatus.dwCurrentState <> SERVICE_RUNNING do
+            while svcStatus.dwCurrentState = SERVICE_START_PENDING do
             begin
             begin
               dwChkP := svcStatus.dwCheckPoint;
               dwChkP := svcStatus.dwCheckPoint;
               Sleep(svcStatus.dwWaitHint);
               Sleep(svcStatus.dwWaitHint);

+ 13 - 1
quicklib.lpk

@@ -16,7 +16,7 @@
       </Parsing>
       </Parsing>
     </CompilerOptions>
     </CompilerOptions>
     <Version Major="1"/>
     <Version Major="1"/>
-    <Files Count="16">
+    <Files Count="19">
       <Item1>
       <Item1>
         <Filename Value="Quick.Console.pas"/>
         <Filename Value="Quick.Console.pas"/>
         <UnitName Value="Quick.Console"/>
         <UnitName Value="Quick.Console"/>
@@ -81,6 +81,18 @@
         <Filename Value="Quick.Config.Provider.Json.pas"/>
         <Filename Value="Quick.Config.Provider.Json.pas"/>
         <UnitName Value="Quick.Config.Provider.Json"/>
         <UnitName Value="Quick.Config.Provider.Json"/>
       </Item16>
       </Item16>
+      <Item17>
+        <Filename Value="Quick.Config.Provider.Registry.pas"/>
+        <UnitName Value="Quick.Config.Provider.Registry"/>
+      </Item17>
+      <Item18>
+        <Filename Value="Quick.Json.fpc.Compatibility.pas"/>
+        <UnitName Value="Quick.Json.fpc.Compatibility"/>
+      </Item18>
+      <Item19>
+        <Filename Value="Quick.JSONRecord.pas"/>
+        <UnitName Value="Quick.JSONRecord"/>
+      </Item19>
     </Files>
     </Files>
     <RequiredPkgs Count="3">
     <RequiredPkgs Count="3">
       <Item1>
       <Item1>

+ 2 - 1
quicklib.pas

@@ -11,7 +11,8 @@ uses
   Quick.Console, Quick.AppService, Quick.Base64, Quick.Chrono, Quick.Commons, 
   Quick.Console, Quick.AppService, Quick.Base64, Quick.Chrono, Quick.Commons, 
   Quick.FileMonitor, Quick.Files, Quick.Format, Quick.Log, Quick.Network, 
   Quick.FileMonitor, Quick.Files, Quick.Format, Quick.Log, Quick.Network, 
   Quick.Process, Quick.Service, Quick.SMTP, Quick.Threads, Quick.Config, 
   Quick.Process, Quick.Service, Quick.SMTP, Quick.Threads, Quick.Config, 
-  Quick.Config.Provider.Json;
+  Quick.Config.Provider.Json, Quick.Config.Provider.Registry, 
+  Quick.Json.fpc.Compatibility, Quick.JSONRecord;
 
 
 implementation
 implementation
 
 

+ 175 - 0
samples/delphi/QuickAutoMapper/AutoMappingObjects.dpr

@@ -0,0 +1,175 @@
+program AutoMappingObjects;
+
+{$APPTYPE CONSOLE}
+
+{$R *.res}
+
+uses
+  System.SysUtils,
+  Quick.Commons,
+  Quick.Console,
+  Quick.JSONRecord,
+  Quick.AutoMapper;
+
+type
+
+  TJob = record
+    Name : string;
+    DateFrom : TDateTime;
+    DateTo : TDateTime;
+  end;
+
+  TCarType = (ctOil, ctDiesel);
+
+  TCar = class
+  private
+    fModel : string;
+    fCarType : TCarType;
+  published
+    property Model : string read fModel write fModel;
+    property CarType : TCarType read fCarType write fCarType;
+  end;
+
+  TUserBase = class(TJsonRecord)
+  private
+    fName : string;
+    fAge : Integer;
+    fCreationDate : TDateTime;
+    fNumbers : TArray<Integer>;
+  published
+    property Name : string read fName write fName;
+    property Age : Integer read fAge write fAge;
+    property CreationDate : TDateTime read fCreationDate write fCreationDate;
+    property Numbers : TArray<Integer> read fNumbers write fNumbers;
+  end;
+
+  TUser = class(TUserBase)
+  private
+    fId : Int64;
+    fCash : Integer;
+    fJob : TJob;
+    fCar : TCar;
+  public
+    constructor Create;
+    destructor Destroy; override;
+  published
+    property Id : Int64 read fId write fId;
+    property Cash : Integer read fCash write fCash;
+    property Job : TJob read fJob write fJob;
+    property Car : TCar read fCar write fCar;
+  end;
+
+  TUser2 = class(TUserBase)
+  private
+    fIdUser : Int64;
+    fName : string;
+    fAge : Integer;
+    fNumbers : TArray<Integer>;
+    fJob : TJob;
+    fMoney : Integer;
+    fCar : TCar;
+  public
+    constructor Create;
+    destructor Destroy; override;
+  published
+    property IdUser : Int64 read fIdUser write fIdUser;
+    property Name : string read fName write fName;
+    property Age : Integer read fAge write fAge;
+    property Numbers : TArray<Integer> read fNumbers write fNumbers;
+    property Money : Integer read fMoney write fMoney;
+    property Job : TJob read fJob write fJob;
+    property Car : TCar read fCar write fCar;
+  end;
+
+var
+  User : TUser;
+  User2 : TUser2;
+  UserClone : TUser;
+  job : TJob;
+  AutoMapper : TAutoMapper<TUser,TUser2>;
+
+{ TUser }
+
+constructor TUser.Create;
+begin
+  fCar := TCar.Create;
+end;
+
+destructor TUser.Destroy;
+begin
+  fCar.Free;
+  inherited;
+end;
+
+{ TUser2 }
+
+constructor TUser2.Create;
+begin
+  fCar := TCar.Create;
+end;
+
+destructor TUser2.Destroy;
+begin
+  fCar.Free;
+  inherited;
+end;
+
+begin
+  ReportMemoryLeaksOnShutdown := True;
+  try
+    User := TUser.Create;
+    User.Id := 17;
+    User.CreationDate := Now();
+    User.Name := 'Juan';
+    User.Age := 30;
+    User.Numbers := [1,2,3,4,5];
+    User.Cash := 3500;
+    job.Name := 'Designer';
+    job.DateFrom := IncMonth(Now(),-12);
+    job.DateTo := Now();
+    User.Job := job;
+    User.Car.Model := 'Ferrari';
+    User.Car.CarType := ctOil;
+    //User2 := TMapper<TUser2>.Map(User);
+    AutoMapper := TAutoMapper<TUser,TUser2>.Create;
+    try
+      AutoMapper.CustomMapping.AddMap('Cash','Money');
+      AutoMapper.CustomMapping.AddMap('Id','IdUser');
+      User2 := AutoMapper.Map(User);
+      //User2 := TUser2.Create;
+      //User.MapTo(User2);
+      //User2.MapFrom(User);
+      //User2 := User.Map<TUser2>;
+      //UserClone := User.Clone as TUser;
+      //User2 := TUser2(User.Clone);
+      //User2 := TMapper<TUserBase>.Clone(User) as TUser2;
+
+      cout('COMPARE USER VS USER2',etTrace);
+      cout('User.Id = %d / User2.IdUser = %d',[User.Id,User2.IdUser],etInfo);
+      cout('User.CreationDate = %s / User2.CreationDate = %s',[DateTimeToStr(User.CreationDate),DateTimetoStr(User2.CreationDate)],etInfo);
+      cout('User.Name = %s / User2.Name = %s',[User.Name,User2.Name],etInfo);
+      cout('User.Age = %d / User2.Age = %d',[User.Age,User2.Age],etInfo);
+      cout('User.Numbers = %d / User2.Numbers = %d',[User.Numbers[1],User2.Numbers[1]],etInfo);
+      cout('User.Cash = %d / User2.Money = %d',[User.Cash,User2.Money],etInfo);
+      cout('User.Job.Name = %s / User2.Job.Name = %s',[User.Job.Name,User2.Job.Name],etInfo);
+      cout('User.Job.DateFrom = %s / User2.Job.DateFrom = %s',[DateTimeToStr(User.Job.DateFrom),DateTimeToStr(User2.Job.DateFrom)],etInfo);
+      cout('User.Car.Model = %s / User2.Car.Model = %s',[User.Car.Model,User2.Car.Model],etInfo);
+
+      cout(' ',etInfo);
+      cout('USER AS JSON RESULT',etTrace);
+      cout('%s',[User.ToJson],etInfo);
+      cout(' ',etInfo);
+      cout('USER2 AS JSON RESULT',etTrace);
+      cout('%s',[User2.ToJson],etInfo);
+
+    finally
+      AutoMapper.Free;
+      User.Free;
+      User2.Free;
+    end;
+    ConsoleWaitForEnterKey;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.

+ 621 - 0
samples/delphi/QuickAutoMapper/AutoMappingObjects.dproj

@@ -0,0 +1,621 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <ProjectGuid>{3F29272C-7851-41C3-B29E-C0ACD8029C21}</ProjectGuid>
+        <ProjectVersion>18.4</ProjectVersion>
+        <FrameworkType>None</FrameworkType>
+        <MainSource>AutoMappingObjects.dpr</MainSource>
+        <Base>True</Base>
+        <Config Condition="'$(Config)'==''">Debug</Config>
+        <Platform Condition="'$(Platform)'==''">Win32</Platform>
+        <TargetedPlatforms>1</TargetedPlatforms>
+        <AppType>Console</AppType>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
+        <Base_Android>true</Base_Android>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Base)'=='true') or '$(Base_iOSDevice32)'!=''">
+        <Base_iOSDevice32>true</Base_iOSDevice32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Base)'=='true') or '$(Base_iOSDevice64)'!=''">
+        <Base_iOSDevice64>true</Base_iOSDevice64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Base)'=='true') or '$(Base_iOSSimulator)'!=''">
+        <Base_iOSSimulator>true</Base_iOSSimulator>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Base)'=='true') or '$(Base_OSX32)'!=''">
+        <Base_OSX32>true</Base_OSX32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
+        <Base_Win32>true</Base_Win32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
+        <Base_Win64>true</Base_Win64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+        <Cfg_1>true</Cfg_1>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
+        <Cfg_1_Win32>true</Cfg_1_Win32>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+        <Cfg_2>true</Cfg_2>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base)'!=''">
+        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
+        <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
+        <DCC_E>false</DCC_E>
+        <DCC_N>false</DCC_N>
+        <DCC_S>false</DCC_S>
+        <DCC_F>false</DCC_F>
+        <DCC_K>false</DCC_K>
+        <DCC_UsePackage>RESTComponents;FireDACIBDriver;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
+        <SanitizedProjectName>AutoMappingObjects</SanitizedProjectName>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Android)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;CoolTrayIcon_D210_XE7;IndyIPClient;dbxcds;dsnapxml;dbrtl;IndyProtocols;$(DCC_UsePackage)</DCC_UsePackage>
+        <Android_LauncherIcon36>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png</Android_LauncherIcon36>
+        <Android_LauncherIcon48>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png</Android_LauncherIcon48>
+        <Android_LauncherIcon72>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png</Android_LauncherIcon72>
+        <Android_LauncherIcon96>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png</Android_LauncherIcon96>
+        <Android_LauncherIcon144>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png</Android_LauncherIcon144>
+        <Android_SplashImage426>$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png</Android_SplashImage426>
+        <Android_SplashImage470>$(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png</Android_SplashImage470>
+        <Android_SplashImage640>$(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png</Android_SplashImage640>
+        <Android_SplashImage960>$(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png</Android_SplashImage960>
+        <EnabledSysJars>android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services-ads-7.0.0.dex.jar;google-play-services-analytics-7.0.0.dex.jar;google-play-services-base-7.0.0.dex.jar;google-play-services-identity-7.0.0.dex.jar;google-play-services-maps-7.0.0.dex.jar;google-play-services-panorama-7.0.0.dex.jar;google-play-services-plus-7.0.0.dex.jar;google-play-services-wallet-7.0.0.dex.jar</EnabledSysJars>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSDevice32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSDevice64)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FrameViewer;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;TMSFMXPackPkgDXE11;dbxcds;dsnapxml;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSSimulator)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;dbexpress;IndyCore;dsnap;bindengine;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;dbrtl;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_OSX32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;inetdb;FmxTeeUI;fmx;fmxdae;dbexpress;IndyCore;dsnap;bindengine;DBXMySQLDriver;FireDACMySQLDriver;FireDACCommonODBC;bindcompdbx;IndyIPCommon;IndyIPServer;IndySystem;fmxFireDAC;FireDACPgDriver;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;ibxbindings;fmxobj;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;dbrtl;inetdbxpress;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;UbuntuProgressPackage;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;svnui;JvGlobus;FireDACADSDriver;JvPluginSystem;JvMM;tmsxlsdXE11;vcltouch;JvBands;vcldb;bindcompfmx;svn;Intraweb;JvJans;JvNet;inetdb;JvAppFrm;EssentialsDR;vcwdedXE11;vcwdXE11;FmxTeeUI;JvDotNetCtrls;AbbreviaVCLD;fmx;fmxdae;tmsdXE11;vclib;JvWizards;tmsexdXE11;dbexpress;IndyCore;vclx;JvPageComps;dsnap;JvDB;VCLRESTComponents;JclDeveloperTools;vclie;bindengine;DBXMySQLDriver;JvCmp;FireDACMySQLDriver;JvHMI;FireDACCommonODBC;LockBoxDR;bindcompdbx;IndyIPCommon;JvCustom;advchartdedxe11;vcl;IndyIPServer;GR32_D;JvXPCtrls;PngComponents;IndySystem;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;vclimg;madBasic_;TeeDB;Jcl;FrameViewer;JvCore;JvCrypt;FireDACPgDriver;ibmonitor;FMXTee;SevenZippro;DbxCommonDriver;JvDlgs;JvRuntimeDesign;ibxpress;Tee;JvManagedThreads;xmlrtl;ibxbindings;fmxobj;vclwinx;JvTimeFramework;rtl;GR32_R;DbxClientDriver;CustomIPTransport;vcldsnap;JvSystem;JvStdCtrls;bindcomp;appanalytics;CoolTrayIcon_D210_XE7;tmswizdXE11;nTrayIcon;IndyIPClient;bindcompvcl;TeeUI;TMSFMXPackPkgDXE11;JvDocking;dbxcds;VclSmp;JvPascalInterpreter;adortl;KernowSoftwareFMX;JclVcl;dsnapxml;dbrtl;inetdbxpress;IndyProtocols;JvControls;JvPrintPreview;Analog_XE7;JclContainers;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win64)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;vcltouch;vcldb;bindcompfmx;Intraweb;inetdb;EssentialsDR;vcwdXE11;FmxTeeUI;AbbreviaVCLD;fmx;fmxdae;tmsdXE11;vclib;tmsexdXE11;dbexpress;IndyCore;vclx;dsnap;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACMySQLDriver;FireDACCommonODBC;bindcompdbx;IndyIPCommon;vcl;IndyIPServer;IndySystem;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDACPgDriver;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;Tee;xmlrtl;ibxbindings;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;dsnapxml;dbrtl;inetdbxpress;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_ConsoleTarget>true</DCC_ConsoleTarget>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1)'!=''">
+        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+        <DCC_DebugDCUs>true</DCC_DebugDCUs>
+        <DCC_Optimize>false</DCC_Optimize>
+        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
+        <DCC_RemoteDebug>false</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2)'!=''">
+        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+        <DCC_DebugInformation>0</DCC_DebugInformation>
+    </PropertyGroup>
+    <ItemGroup>
+        <DelphiCompile Include="$(MainSource)">
+            <MainSource>MainSource</MainSource>
+        </DelphiCompile>
+        <BuildConfiguration Include="Release">
+            <Key>Cfg_2</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Base">
+            <Key>Base</Key>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Debug">
+            <Key>Cfg_1</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+    </ItemGroup>
+    <ProjectExtensions>
+        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
+        <Borland.ProjectType>Application</Borland.ProjectType>
+        <BorlandProject>
+            <Delphi.Personality>
+                <Source>
+                    <Source Name="MainSource">AutoMappingObjects.dpr</Source>
+                </Source>
+            </Delphi.Personality>
+            <Deployment Version="3">
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgsqlite3.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="Win32\Debug\AutoMappingObjects.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win32">
+                        <RemoteName>AutoMappingObjects.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployClass Name="AdditionalDebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidClassesDexFile">
+                    <Platform Name="Android">
+                        <RemoteDir>classes</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidGDBServer">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeArmeabiFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeMipsFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\mips</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidServiceOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashImageDef">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStyles">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_DefaultAppIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon144">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon36">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-ldpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon48">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon72">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon96">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage426">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-small</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage470">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-normal</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage640">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-large</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage960">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xlarge</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyFramework">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyModule">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.dll;.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="DependencyPackage">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="File">
+                    <Platform Name="Android">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1024">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1536">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch2048">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch768">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch320">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640x1136">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectAndroidManifest">
+                    <Platform Name="Android">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceDebug">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceResourceRules">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSEntitlements">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSInfoPList">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSResource">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXEntitlements">
+                    <Platform Name="OSX32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXInfoPList">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXResource">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="ProjectOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Linux64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectUWPManifest">
+                    <Platform Name="Win32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo150">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo44">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
+            </Deployment>
+            <Platforms>
+                <Platform value="Android">False</Platform>
+                <Platform value="iOSDevice32">False</Platform>
+                <Platform value="iOSDevice64">False</Platform>
+                <Platform value="iOSSimulator">False</Platform>
+                <Platform value="OSX32">False</Platform>
+                <Platform value="Win32">True</Platform>
+                <Platform value="Win64">False</Platform>
+            </Platforms>
+        </BorlandProject>
+        <ProjectFileVersion>12</ProjectFileVersion>
+    </ProjectExtensions>
+    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
+    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
+    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
+</Project>

二进制
samples/delphi/QuickAutoMapper/AutoMappingObjects.res


+ 1 - 3
samples/delphi/QuickJsonSerializer/JsonSerializer.dpr

@@ -3,9 +3,7 @@ program JsonSerializer;
 uses
 uses
   System.StartUpCopy,
   System.StartUpCopy,
   FMX.Forms,
   FMX.Forms,
-  main in 'C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\main.pas' {Form1},
-  jsonit in 'C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\jsonit.pas',
-  Quick.Json.Serializer in 'C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\Quick.Json.Serializer.pas';
+  main in 'main.pas' {Form1};
 
 
 {$R *.res}
 {$R *.res}
 
 

+ 1 - 3
samples/delphi/QuickJsonSerializer/JsonSerializer.dproj

@@ -246,11 +246,9 @@
         <DelphiCompile Include="$(MainSource)">
         <DelphiCompile Include="$(MainSource)">
             <MainSource>MainSource</MainSource>
             <MainSource>MainSource</MainSource>
         </DelphiCompile>
         </DelphiCompile>
-        <DCCReference Include="C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\main.pas">
+        <DCCReference Include="main.pas">
             <Form>Form1</Form>
             <Form>Form1</Form>
         </DCCReference>
         </DCCReference>
-        <DCCReference Include="C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\jsonit.pas"/>
-        <DCCReference Include="C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\Quick.Json.Serializer.pas"/>
         <BuildConfiguration Include="Debug">
         <BuildConfiguration Include="Debug">
             <Key>Cfg_2</Key>
             <Key>Cfg_2</Key>
             <CfgParent>Base</CfgParent>
             <CfgParent>Base</CfgParent>

+ 39 - 0
samples/delphi/QuickJsonSerializer/main.fmx

@@ -0,0 +1,39 @@
+object Form1: TForm1
+  Left = 0
+  Top = 0
+  Caption = 'Form1'
+  ClientHeight = 552
+  ClientWidth = 1182
+  FormFactor.Width = 320
+  FormFactor.Height = 480
+  FormFactor.Devices = [Desktop]
+  OnCreate = FormCreate
+  OnClose = FormClose
+  DesignerMasterStyle = 0
+  object Memo1: TMemo
+    Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+    DataDetectorTypes = []
+    Position.X = 8.000000000000000000
+    Position.Y = 8.000000000000000000
+    Size.Width = 1169.000000000000000000
+    Size.Height = 497.000000000000000000
+    Size.PlatformDefault = False
+    TabOrder = 0
+    Viewport.Width = 1165.000000000000000000
+    Viewport.Height = 493.000000000000000000
+  end
+  object btnToJson: TButton
+    Position.X = 544.000000000000000000
+    Position.Y = 520.000000000000000000
+    TabOrder = 2
+    Text = 'ToJson'
+    OnClick = btnToJsonClick
+  end
+  object btnFromJson: TButton
+    Position.X = 656.000000000000000000
+    Position.Y = 520.000000000000000000
+    TabOrder = 1
+    Text = 'FromJson'
+    OnClick = btnFromJsonClick
+  end
+end

+ 269 - 0
samples/delphi/QuickJsonSerializer/main.pas

@@ -0,0 +1,269 @@
+unit main;
+
+interface
+
+uses
+  System.SysUtils,
+  System.Types,
+  System.UITypes,
+  System.Classes,
+  System.Variants,
+  System.Generics.Collections,
+  FMX.Types,
+  FMX.Controls,
+  FMX.Forms,
+  FMX.Graphics,
+  FMX.Dialogs,
+  FMX.Controls.Presentation,
+  FMX.ScrollBox,
+  FMX.Memo,
+  FMX.StdCtrls,
+  Quick.JsonRecord,
+  Quick.Base64,
+  Quick.Json.Serializer;
+
+type
+
+  TID = Int64;
+
+  TContactType = (ctInternal, ctExternal);
+  TMessageState = (msPending, msSent, msNotSent);
+
+  TRecipientArray = array of TID;
+
+  TRecipient = record
+    ID : TID;
+    RType : TContactType;
+    Confirm : TMessageState;
+  end;
+
+  TGenre = (gnMale, gnFemale);
+
+  TGroupType = (gtInternal, gtExternal);
+
+  TDayOfWeek = (wdSunday, wdMonday, wdThuesday, wdWednesday, wdThursday, wdFriday, wdSaturday);
+
+  TUserStatus = (usAtOffice, usAtHome, usOnVacation);
+
+  TDays = set of TDayOfWeek;
+
+const
+  DEF_WORKDAYS : TDays = [wdMonday, wdThuesday, wdWednesday, wdThursday, wdFriday];
+  DEF_WEEKEND : TDays = [wdSaturday, wdSunday];
+
+type
+
+  TDepartment = record
+    Id : TID;
+    Name : string;
+  end;
+
+  TContactIdArray = array of TID;
+
+  TGroup = class
+  private
+    fId : TID;
+    fGType : TGroupType;
+  published
+    property Id : TID read fId write fId;
+    property GType : TGroupType read fGType write fGType;
+  end;
+
+  TOptions = class
+  private
+    fOption1 : Integer;
+    fOption2 : string;
+    fAllowGroups : TGroupType;
+  published
+    property Option1 : Integer read fOption1 write fOption1;
+    property Option2 : string read fOption2 write fOption2;
+    property AllowGroups : TGroupType read fAllowGroups write fAllowGroups;
+  end;
+
+  TConnectionInfo = record
+    IP : string;
+    ConnectionDate : TDateTime;
+  end;
+
+  TConnectionArray = array of TConnectionInfo;
+
+  TGroupList = TObjectList<TGroup>;
+
+  TWorkingTime = class
+  private
+    fName : string;
+    fWorkDays : TDays;
+    fFreeDays : TDays;
+  published
+    property Name : string read fName write fName;
+    property WorkDays : TDays read fWorkDays write fWorkDays;
+    property FreeDays : TDays read fFreeDays write fFreeDays;
+  end;
+
+  TLevelPrivilege = array of TID;
+
+  TUser = class(TJsonRecord)
+  private
+    fId : TID;
+    fName : string;
+    fSurname : string;
+    fAge : Integer;
+    fAddress : string;
+    fOptions : TOptions;
+    fLastConnections : TConnectionArray;
+    fMarried : Boolean;
+    fWorkingTime : TWorkingTime;
+    fGenre : TGenre;
+    fDepartment : TDepartment;
+    fBalance : Double;
+    fHireDate : TDateTime;
+    fLevelPrivilege : TLevelPrivilege;
+    fObservations : string;
+    fStatus : TUserStatus;
+    fGroups : TGroupList;
+  public
+    constructor Create;
+    destructor Destroy; override;
+  published
+    [TCommentProperty('Is user Id')]
+    property Id : TID read fId write fId;
+    property Name : string read fName write fName;
+    property Surname : string read fSurname write fSurname;
+    property Age : Integer read fAge write fAge;
+    [TCommentProperty('gnFemale or gnMale')]
+    property Genre : TGenre read fGenre write fGenre;
+    property Department : TDepartment read fDepartment write fDepartment;
+    property Address : string read fAddress write fAddress;
+    property Balance : Double read fBalance write fBalance;
+    [TCustomNameProperty('IsMarried')]
+    property Married : Boolean read fMarried write fMarried;
+    property WorkingTime : TWorkingTime read fWorkingTime write fWorkingTime;
+    property HireDate : TDateTime read fHireDate write fHireDate;
+    [TCommentProperty('Possible values = usAtOffice, usAtHome or usOnVacation')]
+    property Status : TUserStatus read fStatus write fStatus;
+    property LastConnections : TConnectionArray read fLastConnections write fLastConnections;
+    property Observations : string read fObservations write fObservations;
+    property LevelPrivilege : TLevelPrivilege read fLevelPrivilege write fLevelPrivilege;
+    property Options : TOptions read fOptions write fOptions;
+    property Groups : TGroupList read fGroups write fGroups;
+  end;
+
+  TUserList = TObjectList<TUser>;
+
+
+  TForm1 = class(TForm)
+    Memo1: TMemo;
+    btnToJson: TButton;
+    btnFromJson: TButton;
+    procedure FormCreate(Sender: TObject);
+    procedure btnToJsonClick(Sender: TObject);
+    procedure btnFromJsonClick(Sender: TObject);
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+  end;
+
+var
+  Form1: TForm1;
+  Serializer : TJsonSerializer;
+  User : TUser;
+  User2 : TUser;
+  UserList : TUserList;
+
+implementation
+
+{$R *.fmx}
+
+procedure TForm1.btnFromJsonClick(Sender: TObject);
+var
+  s : string;
+begin
+  if User2 <> nil then User2.Free;
+  User2 := TUser.Create;
+  User2.FromJson(Memo1.Text);
+  //User2.CreateFromJson(Memo1.Text);
+  Memo1.Lines.Add('User2 as json:');
+  Memo1.Lines.Add(User2.ToJson);
+  Memo1.Lines.Add(Format('Groups.OwnedObjects=%s',[BoolToStr(User2.Groups.OwnsObjects,True)]));
+  Memo1.Lines.Add(Format('Groups.Count=%d',[User2.Groups.Count]));
+  Memo1.Lines.Add(Format('Groups.Capacity=%d',[User2.Groups.Capacity]));
+  ShowMessage(Format('%s %s from %s',[User2.Name,User2.Surname,User2.Address]));
+end;
+
+procedure TForm1.btnToJsonClick(Sender: TObject);
+begin
+  Memo1.Text := User.ToJson;
+end;
+
+procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  if Assigned(User) then User.Free;
+  if Assigned(User2) then User2.Free;
+  Serializer.Free;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+var
+  lastcon : TConnectionInfo;
+  group : TGroup;
+  department : TDepartment;
+begin
+  serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
+  user := TUser.Create;
+  user.Id := 77;
+  user.Name := 'Joe';
+  user.Surname := 'Smith Valdés';
+  user.Age := 30;
+  user.Married := True;
+  user.Address := 'Sunset st. 2 \b';
+  user.Options.Option1 := 1;
+  user.Options.Option2 := 'good';
+  user.Options.AllowGroups := gtExternal;
+  user.Balance := 99.9;
+  user.HireDate := Now();
+  user.LevelPrivilege := [1,2,3,4];
+  user.WorkingTime.Name:= 'WeekConfig';
+  user.WorkingTime.WorkDays := DEF_WORKDAYS;
+  user.WorkingTime.FreeDays := DEF_WEEKEND;
+  user.Observations := 'Good aptitude';
+  department.Id := 10;
+  department.Name := 'IT';
+  user.Department := department;
+  //user.Status := TUserStatus.usOnVacation;
+  //lastcon.IP := '127.0.0.1';
+  //lastcon.ConnectionDate := Now();
+  //User.LastConnections := [lastcon];
+  //lastcon.IP := '192.0.0.1';
+  //lastcon.ConnectionDate := Now();
+  //User.LastConnections := User.LastConnections + [lastcon];
+  group := TGroup.Create;
+  group.Id := 1;
+  group.GType := gtInternal;
+  user.Groups.Add(group);
+  group := TGroup.Create;
+  group.Id := 2;
+  group.GType := gtExternal;
+  user.Groups.Add(group);
+ end;
+
+
+{ TUser }
+
+constructor TUser.Create;
+begin
+  fOptions := TOptions.Create;
+  fWorkingTime := TWorkingTime.Create;
+  fGroups := TGroupList.Create(True);
+end;
+
+destructor TUser.Destroy;
+begin
+  fOptions.Free;
+  fWorkingTime.Free;
+  fGroups.Free;
+  inherited;
+end;
+
+end.

+ 64 - 0
samples/fpc/AutoMapper/AutoMapperObjects.lpi

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="AutoMapperObjects"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="QuickLib"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="AutoMapperObjects.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="AutoMapperObjects"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 171 - 0
samples/fpc/AutoMapper/AutoMapperObjects.lpr

@@ -0,0 +1,171 @@
+program AutoMapperObjects;
+
+uses
+  SysUtils,
+  Quick.Commons,
+  Quick.Console,
+  Quick.JSONRecord,
+  Quick.AutoMapper;
+
+type
+
+  TJob = class
+  private
+    fName : string;
+    fDateFrom : TDateTime;
+    fDateTo : TDateTime;
+  published
+    property Name : string read fName write fName;
+    property DateFrom : TDateTime read fDateFrom write fDateFrom;
+    property DateTo : TDateTime read fDateTo write fDateTo;
+  end;
+
+  TCarType = (ctOil, ctDiesel);
+
+  TCar = class
+  private
+    fModel : string;
+    fCarType : TCarType;
+  published
+    property Model : string read fModel write fModel;
+    property CarType : TCarType read fCarType write fCarType;
+  end;
+
+  TArrayOfInteger = array of Integer;
+
+  TUserBase = class(TJsonRecord)
+  private
+    fName : string;
+    fAge : Integer;
+    fCreationDate : TDateTime;
+    fNumbers : TArrayOfInteger;
+  published
+    property Name : string read fName write fName;
+    property Age : Integer read fAge write fAge;
+    property CreationDate : TDateTime read fCreationDate write fCreationDate;
+    property Numbers : TArrayOfInteger read fNumbers write fNumbers;
+  end;
+
+  TUser = class(TUserBase)
+  private
+    fId : Int64;
+    fCash : Integer;
+    fJob : TJob;
+    fCar : TCar;
+  public
+    constructor Create;
+    destructor Destroy; override;
+  published
+    property Id : Int64 read fId write fId;
+    property Cash : Integer read fCash write fCash;
+    property Job : TJob read fJob write fJob;
+    property Car : TCar read fCar write fCar;
+  end;
+
+  TUser2 = class(TUserBase)
+  private
+    fIdUser : Int64;
+    fJob : TJob;
+    fMoney : Integer;
+    fCar : TCar;
+  public
+    constructor Create;
+    destructor Destroy; override;
+  published
+    property IdUser : Int64 read fIdUser write fIdUser;
+    property Money : Integer read fMoney write fMoney;
+    property Job : TJob read fJob write fJob;
+    property Car : TCar read fCar write fCar;
+  end;
+
+var
+  User : TUser;
+  User2 : TUser2;
+  AutoMapper : specialize TAutoMapper<TUser,TUser2>;
+
+{ TUser }
+
+constructor TUser.Create;
+begin
+  fCar := TCar.Create;
+  fJob := TJob.Create;
+end;
+
+destructor TUser.Destroy;
+begin
+  fCar.Free;
+  fJob.Free;
+  inherited;
+end;
+
+{ TUser2 }
+
+constructor TUser2.Create;
+begin
+  fCar := TCar.Create;
+  fJob := TJob.Create;
+end;
+
+destructor TUser2.Destroy;
+begin
+  fCar.Free;
+  fJob.Free;
+  inherited;
+end;
+
+begin
+  try
+    User := TUser.Create;
+    User.Id := 17;
+    User.CreationDate := Now();
+    User.Name := 'John Miller';
+    User.Age := 30;
+    User.Numbers := [1,2,3,4,5];
+    User.Cash := 3500;
+    User.Job.Name := 'Designer';
+    User.Job.DateFrom := IncMonth(Now(),-12);
+    User.Job.DateTo := Now();
+    User.Car.Model := 'Ferrari';
+    User.Car.CarType := ctOil;
+    //User2 := TMapper<TUser2>.Map(User);
+    AutoMapper := specialize TAutoMapper<TUser,TUser2>.Create;
+    try
+      AutoMapper.CustomMapping.AddMap('Cash','Money');
+      AutoMapper.CustomMapping.AddMap('Id','IdUser');
+      User2 := AutoMapper.Map(User);
+      //User2 := TUser2.Create;
+      //User.MapTo(User2);
+      //User2.MapFrom(User);
+      //User2 := User.Map<TUser2>;
+      //User2 := TUser2(User.Clone);
+      //User2 := TMapper<TUserBase>.Clone(User) as TUser2;
+
+      cout('COMPARE USER VS USER2',etTrace);
+      cout('User.Id = %d / User2.IdUser = %d',[User.Id,User2.IdUser],etInfo);
+      cout('User.CreationDate = %s / User2.CreationDate = %s',[DateTimeToStr(User.CreationDate),DateTimetoStr(User2.CreationDate)],etInfo);
+      cout('User.Name = %s / User2.Name = %s',[User.Name,User2.Name],etInfo);
+      cout('User.Age = %d / User2.Age = %d',[User.Age,User2.Age],etInfo);
+      //cout('User.Numbers = %d / User2.Numbers = %d',[User.Numbers[1],User2.Numbers[1]],etInfo);
+      cout('User.Cash = %d / User2.Money = %d',[User.Cash,User2.Money],etInfo);
+      cout('User.Job.Name = %s / User2.Job.Name = %s',[User.Job.Name,User2.Job.Name],etInfo);
+      cout('User.Job.DateFrom = %s / User2.Job.DateFrom = %s',[DateTimeToStr(User.Job.DateFrom),DateTimeToStr(User2.Job.DateFrom)],etInfo);
+      cout('User.Car.Model = %s / User2.Car.Model = %s',[User.Car.Model,User2.Car.Model],etInfo);
+
+      cout(' ',etInfo);
+      cout('USER AS JSON RESULT',etTrace);
+      cout('%s',[User.ToJson],etInfo);
+      cout(' ',etInfo);
+      cout('USER2 AS JSON RESULT',etTrace);
+      cout('%s',[User2.ToJson],etInfo);
+
+    finally
+      AutoMapper.Free;
+      User.Free;
+      User2.Free;
+    end;
+    ConsoleWaitForEnterKey;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+end.