Sfoglia il codice sorgente

Merge branch 'develop'

Unknown 7 anni fa
parent
commit
c9222ca0d8
31 ha cambiato i file con 2161 aggiunte e 779 eliminazioni
  1. 1 1
      Quick.Azure.pas
  2. 11 1
      Quick.Commons.pas
  3. 14 31
      Quick.Config.Provider.Json.pas
  4. 21 33
      Quick.Config.pas
  5. 105 0
      Quick.JSONRecord.pas
  6. 564 53
      Quick.Json.Serializer.pas
  7. 134 0
      Quick.Json.fpc.Compatibility.pas
  8. 24 13
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/Main.pas
  9. 1 551
      samples/delphi/QuickConfig/ConfigToFileAndRegistry/Win64/Debug/Config.json
  10. 17 0
      samples/delphi/QuickJsonSerializer/JsonSerializer.dpr
  11. 289 0
      samples/delphi/QuickJsonSerializer/JsonSerializer.dproj
  12. BIN
      samples/delphi/QuickJsonSerializer/JsonSerializer.res
  13. 43 0
      samples/delphi/QuickJsonSerializer/frmMain.fmx
  14. 236 0
      samples/delphi/QuickJsonSerializer/frmMain.pas
  15. 1 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lpi
  16. 1 0
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfig.lpi
  17. 24 6
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.lfm
  18. 101 40
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.pas
  19. BIN
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfig.or
  20. 24 6
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/umain.lfm
  21. 24 6
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.lfm
  22. 101 38
      samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.pas
  23. BIN
      samples/fpc/QuickJsonSerializer/JsonSerializer.ico
  24. 84 0
      samples/fpc/QuickJsonSerializer/JsonSerializer.lpi
  25. 22 0
      samples/fpc/QuickJsonSerializer/JsonSerializer.lpr
  26. BIN
      samples/fpc/QuickJsonSerializer/JsonSerializer.res
  27. BIN
      samples/fpc/QuickJsonSerializer/lib/i386-win32/JsonSerializer.or
  28. BIN
      samples/fpc/QuickJsonSerializer/lib/i386-win32/JsonSerializer.res
  29. 40 0
      samples/fpc/QuickJsonSerializer/lib/i386-win32/main.lfm
  30. 40 0
      samples/fpc/QuickJsonSerializer/main.lfm
  31. 239 0
      samples/fpc/QuickJsonSerializer/main.pas

+ 1 - 1
Quick.Azure.pas

@@ -679,7 +679,7 @@ begin
         AzContainers := BlobService.ListContainers(cNextMarker,AzParams,CloudResponseInfo);
         AzContainers := BlobService.ListContainers(cNextMarker,AzParams,CloudResponseInfo);
         try
         try
           azResponseInfo := GetResponseInfo(CloudResponseInfo);
           azResponseInfo := GetResponseInfo(CloudResponseInfo);
-          if (azResponseInfo.StatusCode = 200) and (Assigned(AzContainer)) then
+          if (azResponseInfo.StatusCode = 200) and (Assigned(AzContainers)) then
           begin
           begin
             for AzContainer in AzContainers do
             for AzContainer in AzContainers do
             begin
             begin

+ 11 - 1
Quick.Commons.pas

@@ -913,6 +913,10 @@ function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
 var
 var
   FmtSettings : TFormatSettings;
   FmtSettings : TFormatSettings;
 {$ENDIF}
 {$ENDIF}
+{$IFDEF FPC}
+var
+  jdate : string;
+{$ENDIF}
 begin
 begin
   {$IFDEF DELPHIXE7_UP}
   {$IFDEF DELPHIXE7_UP}
   Result := ISO8601ToDate(aJsonDate);
   Result := ISO8601ToDate(aJsonDate);
@@ -920,7 +924,13 @@ begin
   FmtSettings.DateSeparator := '-';
   FmtSettings.DateSeparator := '-';
   FmtSettings.TimeSeparator := ':';
   FmtSettings.TimeSeparator := ':';
   FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
   FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
-  Result := StrToDateTime(aJsonDate,FmtSettings);
+    {$IFDEF FPC}
+    jdate := StringReplace(aJsondate,'T',' ',[rfIgnoreCase]);
+    jdate := Copy(jdate,1,Pos('.',jdate)-1);
+    Result := StrToDateTime(jdate,FmtSettings);
+    {$ELSE}
+    Result := StrToDateTime(aJsonDate,FmtSettings);
+    {$ENDIF}
   {$ENDIF}
   {$ENDIF}
 end;
 end;
 
 

+ 14 - 31
Quick.Config.Provider.Json.pas

@@ -45,13 +45,13 @@ uses
     System.JSON.Types,
     System.JSON.Types,
     System.JSON.Serializers,
     System.JSON.Serializers,
   {$ELSE}
   {$ELSE}
+    Quick.Json.Serializer,
     {$IFDEF FPC}
     {$IFDEF FPC}
     fpjson,
     fpjson,
     fpjsonrtti,
     fpjsonrtti,
     {$ELSE}
     {$ELSE}
     Rest.Json.Types,
     Rest.Json.Types,
     System.JSON,
     System.JSON,
-    Rest.Json,
     {$ENDIF}
     {$ENDIF}
   {$ENDIF}
   {$ENDIF}
   Quick.Config;
   Quick.Config;
@@ -81,12 +81,7 @@ end;
 procedure TAppConfigJsonProvider<T>.Load(var cConfig : T);
 procedure TAppConfigJsonProvider<T>.Load(var cConfig : T);
 var
 var
   json : TStrings;
   json : TStrings;
-  {$IFDEF DELPHIRX102_UP}
-    Serializer : TJsonSerializer;
-  {$ENDIF}
-  {$IFDEF FPC}
-    streamer : TJSONDeStreamer;
-  {$ENDIF}
+  Serializer : TJsonSerializer;
   NewObj : T;
   NewObj : T;
 begin
 begin
   //create object with rtti if nil
   //create object with rtti if nil
@@ -116,18 +111,15 @@ begin
           Serializer.Free;
           Serializer.Free;
         end;
         end;
       {$ELSE}
       {$ELSE}
-        {$IFDEF FPC}
-        streamer := TJSONDeStreamer.Create(nil);
+        serializer := TJsonSerializer.Create(slPublishedProperty);
         try
         try
-          //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
-          Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
-          Streamer.JsonToObject(json.Text,NewObj);
+          //Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+          //Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+          serializer.JsonToObject(cConfig,json.Text);
+          Exit;
         finally
         finally
-          Streamer.Free;
+          serializer.Free;
         end;
         end;
-        {$ELSE}
-        TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json.Text)));
-        {$ENDIF}
       {$ENDIF}
       {$ENDIF}
       if Assigned(cConfig) then cConfig.Free;
       if Assigned(cConfig) then cConfig.Free;
       cConfig := NewObj;
       cConfig := NewObj;
@@ -142,12 +134,7 @@ end;
 procedure TAppConfigJsonProvider<T>.Save(var cConfig : T);
 procedure TAppConfigJsonProvider<T>.Save(var cConfig : T);
 var
 var
   json : TStrings;
   json : TStrings;
-  {$IFDEF DELPHIRX102_UP}
-    Serializer : TJsonSerializer;
-  {$ENDIF}
-  {$IFDEF FPC}
-  streamer : TJsonStreamer;
-  {$ENDIF}
+  Serializer : TJsonSerializer;
   ctx : TRttiContext;
   ctx : TRttiContext;
   rprop : TRttiProperty;
   rprop : TRttiProperty;
 begin
 begin
@@ -172,18 +159,14 @@ begin
           Serializer.Free;
           Serializer.Free;
         end;
         end;
       {$ELSE}
       {$ELSE}
-        {$IFDEF FPC}
-        streamer := TJsonStreamer.Create(nil);
+        serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
         try
         try
-          Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
-          Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
-          json.Text := streamer.ObjectToJSONString(cConfig);
+          //Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+          //Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+          json.Text := serializer.ObjectToJson(cConfig);
         finally
         finally
-          streamer.Free;
+          serializer.Free;
         end;
         end;
-        {$ELSE}
-          json.Text := TJson.ObjectToJsonString(cConfig);
-        {$ENDIF}
       {$ENDIF}
       {$ENDIF}
       json.SaveToFile(fFilename);
       json.SaveToFile(fFilename);
       {$IFDEF FPC}
       {$IFDEF FPC}

+ 21 - 33
Quick.Config.pas

@@ -44,8 +44,11 @@ uses
   {$ELSE}
   {$ELSE}
     {$IFDEF FPC}
     {$IFDEF FPC}
     fpjson,
     fpjson,
-    fpjsonrtti;
+    jsonparser,
+    fpjsonrtti,
+    Quick.Json.Serializer;
     {$ELSE}
     {$ELSE}
+    Quick.Json.Serializer,
     DBXJSON,
     DBXJSON,
     System.JSON,
     System.JSON,
     Rest.Json.Types,
     Rest.Json.Types,
@@ -63,12 +66,16 @@ type
     procedure Save(var cConfig : T);
     procedure Save(var cConfig : T);
   end;
   end;
 
 
+  TSerializeProperty = (spPublic, spPublished);
+
   TAppConfigProviderBase<T : class> = class(TInterfacedObject,IAppConfigProvider<T>)
   TAppConfigProviderBase<T : class> = class(TInterfacedObject,IAppConfigProvider<T>)
   private
   private
     fCreateIfNotExists : Boolean;
     fCreateIfNotExists : Boolean;
+    fSerializeLevel : TSerializeProperty;
   public
   public
     constructor Create(var cConfig : T); virtual;
     constructor Create(var cConfig : T); virtual;
     property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
     property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
+    property SerializeLevel : TSerializeProperty read fSerializeLevel write fSerializeLevel;
     function InitObject : T;
     function InitObject : T;
     procedure Load(var cConfig : T); virtual; abstract;
     procedure Load(var cConfig : T); virtual; abstract;
     procedure Save(var cConfig : T); virtual; abstract;
     procedure Save(var cConfig : T); virtual; abstract;
@@ -77,7 +84,7 @@ type
   TApplyConfigEvent = procedure of object;
   TApplyConfigEvent = procedure of object;
 
 
   {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
   {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
-  TAppConfig = class{$IFDEF FPC}(TPersistent){$ENDIF}
+  TAppConfig = class
   private
   private
     {$IFDEF FPC}
     {$IFDEF FPC}
     fOnApplyConfig : TApplyConfigEvent;
     fOnApplyConfig : TApplyConfigEvent;
@@ -110,14 +117,14 @@ type
     procedure FromJSON(const json : string);
     procedure FromJSON(const json : string);
   end;
   end;
 
 
-  {Usage: create a descend class from TAppConfig and add public properties to be loaded/saved
+  {Usage: create a descend class from TAppConfig and add published properties to be loaded/saved
 
 
   TMyConfig = class(TAppConfig)
   TMyConfig = class(TAppConfig)
   private
   private
     fName : string;
     fName : string;
     fSurname : string;
     fSurname : string;
     fStatus : Integer;
     fStatus : Integer;
-  public
+  published
     property Name : string read fName write fName;
     property Name : string read fName write fName;
     property SurName : string read fSurname write fSurname;
     property SurName : string read fSurname write fSurname;
     property Status : Integer read fStatus write fStatus;
     property Status : Integer read fStatus write fStatus;
@@ -135,6 +142,7 @@ implementation
 constructor TAppConfigProviderBase<T>.Create(var cConfig : T);
 constructor TAppConfigProviderBase<T>.Create(var cConfig : T);
 begin
 begin
   fCreateIfNotExists := True;
   fCreateIfNotExists := True;
+  fSerializeLevel := spPublished;
   //create object with rtti
   //create object with rtti
   if Assigned(cConfig) then cConfig.Free;
   if Assigned(cConfig) then cConfig.Free;
   cConfig := InitObject;
   cConfig := InitObject;
@@ -189,14 +197,8 @@ end;
 
 
 
 
 function TAppConfig.ToJSON : string;
 function TAppConfig.ToJSON : string;
-{$IFDEF DELPHIRX102_UP}
 var
 var
   Serializer : TJsonSerializer;
   Serializer : TJsonSerializer;
-{$ENDIF}
-{$IFDEF FPC}
-var
-  streamer : TJsonStreamer;
-{$ENDIF}
 begin
 begin
   Result := '';
   Result := '';
   try
   try
@@ -216,18 +218,14 @@ begin
         Serializer.Free;
         Serializer.Free;
       end;
       end;
     {$ELSE}
     {$ELSE}
-      {$IFDEF FPC}
-      streamer := TJsonStreamer.Create(nil);
+      serializer := TJsonSerializer.Create(slPublishedProperty);
       try
       try
-        Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
-        Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
-        Result := streamer.ObjectToJSON(Self).ToString;
+        //Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+        //Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+        Result := serializer.ObjectToJSON(Self);
       finally
       finally
-        streamer.Free;
+        serializer.Free;
       end;
       end;
-      {$ELSE}
-      Result := TJson.ObjectToJsonString(Self);
-      {$ENDIF}
     {$ENDIF}
     {$ENDIF}
   except
   except
     on e : Exception do raise Exception.Create(e.Message);
     on e : Exception do raise Exception.Create(e.Message);
@@ -235,14 +233,8 @@ begin
 end;
 end;
 
 
 procedure TAppConfig.FromJSON(const json : string);
 procedure TAppConfig.FromJSON(const json : string);
-{$IFDEF DELPHIRX102_UP}
 var
 var
   Serializer : TJsonSerializer;
   Serializer : TJsonSerializer;
-{$ENDIF}
-{$IFDEF FPC}
-var
-  streamer : TJSONDeStreamer;
-{$ENDIF}
 begin
 begin
   try
   try
     {$IFDEF DELPHIRX102_UP}
     {$IFDEF DELPHIRX102_UP}
@@ -261,18 +253,14 @@ begin
         Serializer.Free;
         Serializer.Free;
       end;
       end;
     {$ELSE}
     {$ELSE}
-      {$IFDEF FPC}
-      streamer := TJSONDeStreamer.Create(nil);
+      serializer := TJsonSerializer.Create(slPublishedProperty);
       try
       try
         //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
         //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
-        Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
-        Streamer.JsonToObject(json,Self);
+        //Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+        Self := TAppConfig(serializer.JsonToObject(Self,json));
       finally
       finally
-        Streamer.Free;
+        serializer.Free;
       end;
       end;
-      {$ELSE}
-      TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json)));
-      {$ENDIF}
     {$ENDIF}
     {$ENDIF}
   except
   except
     on e : Exception do raise Exception.Create(e.Message);
     on e : Exception do raise Exception.Create(e.Message);

+ 105 - 0
Quick.JSONRecord.pas

@@ -0,0 +1,105 @@
+{ ***************************************************************************
+
+  Copyright (c) 2015-2018 Kike Pérez
+
+  Unit        : Quick.JSONRecord
+  Description : Serializable class
+  Author      : Kike Pérez
+  Version     : 1.0
+  Created     : 05/05/2018
+  Modified    : 08/07/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.JSONRecord;
+
+{$i QuickLib.inc}
+
+interface
+
+uses
+  Quick.Json.Serializer,
+  Rest.Json.Types;
+
+type
+
+  IJsonable = interface
+  ['{AF71F59C-89A5-4BFB-8227-0CC3068B7671}']
+    procedure FromJson(const aJson : string);
+    function ToJson : string;
+  end;
+
+  TJsonRecord = class(TInterfacedObject,IJsonable)
+    constructor CreateFromJson(const aJson : string);
+    procedure FromJson(const aJson : string);
+    function ToJson : string;
+  end;
+
+implementation
+
+{ TJsonRecord }
+
+constructor TJsonRecord.CreateFromJson(const aJson: string);
+var
+  serializer : TJsonSerializer;
+begin
+  {$IFNDEF FPC}
+  serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
+  {$ELSE}
+  serializer := TJsonSerializer.Create;
+  {$ENDIF}
+  try
+    serializer.JsonToObject(Self,aJson);
+  finally
+    serializer.Free;
+  end;
+end;
+
+procedure TJsonRecord.FromJson(const aJson: string);
+var
+  serializer : TJsonSerializer;
+begin
+  {$IFNDEF FPC}
+  serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
+  {$ELSE}
+  serializer := TJsonSerializer.Create;
+  {$ENDIF}
+  try
+    serializer.JsonToObject(Self,aJson);
+  finally
+    serializer.Free;
+  end;
+end;
+
+function TJsonRecord.ToJson: string;
+var
+  serializer : TJsonSerializer;
+begin
+  {$IFNDEF FPC}
+  serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
+  {$ELSE}
+  serializer := TJsonSerializer.Create;
+  {$ENDIF}
+  try
+    Result := serializer.ObjectToJson(Self);
+  finally
+    serializer.Free;
+  end;
+end;
+
+end.

+ 564 - 53
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    : 30/06/2018
+  Modified    : 08/07/2018
 
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
 
@@ -36,19 +36,21 @@ interface
 uses
 uses
   Classes,
   Classes,
   SysUtils,
   SysUtils,
+  Rtti,
+  TypInfo,
   {$IFDEF FPC}
   {$IFDEF FPC}
-   Rtti,
    rttiutils,
    rttiutils,
-   jsonreader,
-   fpjsonrtti,
    fpjson,
    fpjson,
+   jsonparser,
+   strUtils,
+   //jsonreader,
+   //fpjsonrtti,
+   Quick.Json.fpc.Compatibility,
   {$ELSE}
   {$ELSE}
     {$IFDEF DELPHIXE7_UP}
     {$IFDEF DELPHIXE7_UP}
-    Rtti,
     System.Json,
     System.Json,
     {$ENDIF}
     {$ENDIF}
   {$ENDIF}
   {$ENDIF}
-  TypInfo,
   DateUtils,
   DateUtils,
   Quick.Commons;
   Quick.Commons;
 
 
@@ -57,9 +59,7 @@ type
   EJsonSerializeError = class(Exception);
   EJsonSerializeError = class(Exception);
   EJsonDeserializeError = class(Exception);
   EJsonDeserializeError = class(Exception);
 
 
-  {$IFDEF FPC}
-  TJsonPair = TJsonData;
-  {$ELSE}
+  {$IFNDEF FPC}
   TNotSerializableProperty = class(TCustomAttribute);
   TNotSerializableProperty = class(TCustomAttribute);
 
 
   TCommentProperty = class(TCustomAttribute)
   TCommentProperty = class(TCustomAttribute)
@@ -88,23 +88,46 @@ type
 
 
   TSerializeLevel = (slPublicProperty, slPublishedProperty);
   TSerializeLevel = (slPublicProperty, slPublishedProperty);
 
 
+  PValue = ^TValue;
 
 
   TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
   TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
   strict private
   strict private
     fSerializeLevel : TSerializeLevel;
     fSerializeLevel : TSerializeLevel;
-    function GetValue(aAddr: Pointer; aType: TRTTIType): TValue;
+    function GetValue(aAddr: Pointer; aType: TRTTIType): TValue; overload;
+    function GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue; overload;
     function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
     function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
     function IsGenericList(aObject : TObject) : Boolean;
     function IsGenericList(aObject : TObject) : Boolean;
+    function GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
+    procedure SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue); overload;
+    procedure SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue); overload;
+    {$IFDEF FPC}
+    function FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
+    function GetPropType(aPropInfo: PPropInfo): PTypeInfo;
+    procedure LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
+    {$ENDIF}
     {$IFNDEF FPC}
     {$IFNDEF FPC}
     function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
     function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
     function DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
     function DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
+    {$ELSE}
+    procedure DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
     {$ENDIF}
     {$ENDIF}
     function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
     function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
     function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
     function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
+    {$IFNDEF FPC}
     function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
     function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
+    {$ENDIF}
     function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
     function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
+    {$IFNDEF FPC}
     function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
     function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
+    {$ELSE}
+    function DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
+    {$ENDIF}
+    {$IFNDEF FPC}
     function Serialize(const aName : string; aValue : TValue) : TJSONPair; overload;
     function Serialize(const aName : string; aValue : TValue) : TJSONPair; overload;
+    {$ELSE}
+    function Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
+    function Serialize(const aName : string; aValue : TValue) : TJSONPair;
+    {$ENDIF}
     function Serialize(aObject : TObject) : TJSONObject; overload;
     function Serialize(aObject : TObject) : TJSONObject; overload;
   public
   public
     constructor Create(aSerializeLevel : TSerializeLevel);
     constructor Create(aSerializeLevel : TSerializeLevel);
@@ -122,7 +145,7 @@ resourcestring
 
 
 implementation
 implementation
 
 
-{ TqlJsonSerializer }
+{ TJsonSerializer }
 
 
 {$IFNDEF FPC}
 {$IFNDEF FPC}
 function TJsonSerializer.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
 function TJsonSerializer.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
@@ -189,6 +212,68 @@ begin
     DynArrayClear(pArr,aTypeInfo);
     DynArrayClear(pArr,aTypeInfo);
   end;
   end;
 end;
 end;
+{$ELSE}
+procedure TJsonSerializer.DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
+var
+  rType: PTypeInfo;
+  len: NativeInt;
+  pArr: Pointer;
+  rItemValue: TValue;
+  i: Integer;
+  objClass: TClass;
+  propObj : TObject;
+  rValue : TValue;
+begin
+  if GetTypeData(aTypeInfo).ElType2 = nil then Exit;
+  len := aJsonArray.Count;
+  rType := GetTypeData(aTypeInfo).ElType2;
+  pArr := nil;
+  DynArraySetLength(pArr,aTypeInfo, 1, @len);
+  try
+    TValue.Make(@pArr,aTypeInfo, rValue);
+    for i := 0 to aJsonArray.Count - 1 do
+    begin
+      rItemValue := nil;
+      case rType.Kind of
+        tkClass :
+          begin
+            if aJsonArray.Items[i] is TJSONObject then
+            begin
+              propObj := GetValue(PPByte(rValue.GetReferenceToRawData)^ +GetTypeData(aTypeInfo).elSize * i, GetTypeData(aTypeInfo).ElType2).AsObject;
+              if propObj = nil then
+              begin
+                objClass := GetTypeData(aTypeInfo).ClassType;
+                rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
+              end
+              else
+              begin
+                DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
+              end;
+            end;
+          end;
+        tkRecord :
+          begin
+            {json := TJSONObject(aJsonArray.Items[i]);
+            rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
+                                            rDynArray.ElementType),aObject,json);  }
+          end;
+        tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
+          begin
+            //skip these properties
+          end
+      else
+        begin
+          rItemValue := DeserializeType(aObject,GetTypeData(aTypeInfo).ElType2.Kind,aPropertyName,aJsonArray.Items[i].Value);
+        end;
+      end;
+      if not rItemValue.IsEmpty then rValue.SetArrayElement(i,rItemValue);
+    end;
+    //aProperty.SetValue(aObject,rValue);
+    SetDynArrayProp(aObject,GetPropInfo(aObject,aPropertyName),pArr);
+  finally
+    DynArrayClear(pArr,aTypeInfo);
+  end;
+end;
 {$ENDIF}
 {$ENDIF}
 
 
 {$IFNDEF FPC}
 {$IFNDEF FPC}
@@ -244,7 +329,7 @@ begin
           end;
           end;
       else
       else
         begin
         begin
-          rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.JsonString.ToString);
+          rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.toJson);
         end;
         end;
       end;
       end;
       if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
       if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
@@ -260,11 +345,7 @@ function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TO
 var
 var
   json: TJSONObject;
   json: TJSONObject;
 begin
 begin
-  {$IFNDEF FPC}
-  json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
-  {$ELSE}
-  json := GetJSON(aJson) as TJsonObject;
-  {$ENDIF}
+  json := TJsonObject(TJSONObject.ParseJSONValue(aJson,True));
   try
   try
     Result := DeserializeObject(aObject,json);
     Result := DeserializeObject(aObject,json);
   finally
   finally
@@ -276,11 +357,7 @@ function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObje
 var
 var
   json: TJSONObject;
   json: TJSONObject;
 begin
 begin
-  {$IFNDEF FPC}
-  json := TJSONObject.ParseJSONValue(aJson) as TJSONObject;
-  {$ELSE}
-  json := GetJSON(aJson) as TJsonObject;
-  {$ENDIF}
+  json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
   try
   try
     Result := DeserializeClass(aType,json);
     Result := DeserializeClass(aType,json);
   finally
   finally
@@ -294,11 +371,7 @@ var
 begin
 begin
   json := Serialize(aObject);
   json := Serialize(aObject);
   try
   try
-    {$IFNDEF FPC}
     Result := json.ToJSON;
     Result := json.ToJSON;
-    {$ELSE}
-    Result := json.AsJson;
-    {$ENDIF}
   finally
   finally
     json.Free;
     json.Free;
   end;
   end;
@@ -331,7 +404,9 @@ var
   ctx: TRttiContext;
   ctx: TRttiContext;
   rType: TRttiType;
   rType: TRttiType;
   rProp: TRttiProperty;
   rProp: TRttiProperty;
+  {$IFNDEF FPC}
   attr: TCustomAttribute;
   attr: TCustomAttribute;
+  {$ENDIF}
   propertyname : string;
   propertyname : string;
 begin
 begin
   Result := aObject;
   Result := aObject;
@@ -349,18 +424,22 @@ begin
     try
     try
       for rProp in rType.GetProperties do
       for rProp in rType.GetProperties do
       begin
       begin
+        {$IFNDEF FPC}
         if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
         if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
-            or ((fSerializeLevel = slPublishedProperty) and (IsPublishedProp(aObject,rProp.Name))) then
+            or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
+        {$ENDIF}
         begin
         begin
           if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
           if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
           begin
           begin
             propertyname := rProp.Name;
             propertyname := rProp.Name;
+            {$IFNDEF FPC}
             for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
             for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
             if rProp.Name = 'List' then
             if rProp.Name = 'List' then
             begin
             begin
               Result := DeserializeList(Result,propertyname,aJson);
               Result := DeserializeList(Result,propertyname,aJson);
             end
             end
             else
             else
+            {$ENDIF}
             Result := DeserializeProperty(Result,propertyname,rProp,aJson);
             Result := DeserializeProperty(Result,propertyname,rProp,aJson);
           end;
           end;
         end;
         end;
@@ -377,6 +456,7 @@ begin
   end;
   end;
 end;
 end;
 
 
+{$IFNDEF FPC}
 function TJsonSerializer.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
 function TJsonSerializer.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
 var
 var
   ctx : TRttiContext;
   ctx : TRttiContext;
@@ -403,8 +483,6 @@ begin
   try
   try
     rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
     rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
     i := jarray.Count;
     i := jarray.Count;
-    rProp := rType.GetProperty('Count');
-    rProp.SetValue(aObject,i);
   finally
   finally
     jArray.Free;
     jArray.Free;
   end;
   end;
@@ -424,21 +502,31 @@ begin
         Break;
         Break;
       end;
       end;
     end;
     end;
+    rProp := rType.GetProperty('Count');
+    rProp.SetValue(aObject,i);
   end;
   end;
 end;
 end;
-
+{$ENDIF}
 
 
 function TJsonSerializer.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
 function TJsonSerializer.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
 var
 var
   rValue : TValue;
   rValue : TValue;
+  {$IFNDEF FPC}
   member : TJSONPair;
   member : TJSONPair;
+  {$ELSE}
+  member : TJsonObject;
+  {$ENDIF}
   objClass: TClass;
   objClass: TClass;
   jArray : TJSONArray;
   jArray : TJSONArray;
   json : TJSONObject;
   json : TJSONObject;
-  propinfo : PPropInfo;
 begin
 begin
     Result := aObject;
     Result := aObject;
+    rValue := nil;
+    {$IFNDEF FPC}
     member := TJSONPair(aJson.GetValue(aName));
     member := TJSONPair(aJson.GetValue(aName));
+    {$ELSE}
+    member := TJsonObject(aJson.Find(aName));
+    {$ENDIF}
     if member <> nil then
     if member <> nil then
     begin
     begin
       case aProperty.PropertyType.TypeKind of
       case aProperty.PropertyType.TypeKind of
@@ -446,7 +534,12 @@ begin
           begin
           begin
             jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
             jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
             try
             try
+              {$IFNDEF FPC}
               aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
               aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
+              {$ELSE}
+              DeserializeDynArray(aProperty.PropertyType.Handle,aName,Result,jArray);
+              {$ENDIF}
+              Exit;
             finally
             finally
               jArray.Free;
               jArray.Free;
             end;
             end;
@@ -455,12 +548,20 @@ begin
           begin
           begin
             //if (member.JsonValue is TJSONObject) then
             //if (member.JsonValue is TJSONObject) then
             begin
             begin
-              json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
+              json := TJsonObject(TJSONObject.ParseJSONValue(member.ToJson));
               try
               try
                 if aProperty.GetValue(aObject).AsObject = nil then
                 if aProperty.GetValue(aObject).AsObject = nil then
                 begin
                 begin
+                  {$IFNDEF FPC}
                   objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
                   objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
-                  rValue := DeserializeClass(objClass,json)
+                  rValue := DeserializeClass(objClass,json);
+                  {$ELSE}
+                  objClass := GetObjectPropClass(aObject,aName);
+                  //objClass := GetTypeData(aProperty.PropertyType.Handle)^.ClassType;
+                  rValue := DeserializeClass(objClass,json);
+                  SetObjectProp(aObject,aName,rValue.AsObject);
+                  Exit;
+                  {$ENDIF}
                 end
                 end
                 else
                 else
                 begin
                 begin
@@ -472,6 +573,7 @@ begin
               end;
               end;
             end
             end
           end;
           end;
+        {$IFNDEF FPC}
         tkRecord :
         tkRecord :
           begin
           begin
             json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
             json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
@@ -481,19 +583,29 @@ begin
               json.Free;
               json.Free;
             end;
             end;
           end;
           end;
+        {$ENDIF}
       else
       else
         begin
         begin
-          rValue := DeserializeType(Result,aProperty.PropertyType.TypeKind,aProperty.GetValue(Result).TypeInfo,member.ToJSON);
+          {$IFNDEF FPC}
+          rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
+          {$ELSE}
+          rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
+          if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
+          {$ENDIF}
         end;
         end;
       end;
       end;
+      {$IFNDEF FPC}
       if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
       if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
+      {$ENDIF}
     end;
     end;
 end;
 end;
 
 
+{$IFNDEF FPC}
 function TJsonSerializer.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
 function TJsonSerializer.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
 var
 var
   i : Integer;
   i : Integer;
   value : string;
   value : string;
+  fsettings : TFormatSettings;
 begin
 begin
   try
   try
     value := AnsiDequotedStr(aValue,'"');
     value := AnsiDequotedStr(aValue,'"');
@@ -530,7 +642,8 @@ begin
           end
           end
           else
           else
           begin
           begin
-            Result := StrToFloat(value);
+            fsettings := TFormatSettings.Create;
+            Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
           end;
           end;
         end;
         end;
       tkEnumeration :
       tkEnumeration :
@@ -561,15 +674,97 @@ begin
     end;
     end;
   end;
   end;
 end;
 end;
+{$ELSE}
+function TJsonSerializer.DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
+var
+  value : string;
+  propinfo : PPropInfo;
+  fsettings : TFormatSettings;
+begin
+  try
+    value := AnsiDequotedStr(aValue,'"');
+
+    if value = '' then
+    begin
+      Result := nil;
+      Exit;
+    end;
+    propinfo := GetPropInfo(aObject,aPropertyName);
+    //case propinfo.PropType.Kind of
+    case aType of
+      tkString, tkLString, tkWString, tkUString, tkAString :
+        begin
+          Result := value;
+          //SetStrProp(aObject,propinfo,value);
+        end;
+      tkChar, tkWChar :
+        begin
+          Result := value;
+        end;
+      tkInteger :
+        begin
+          Result := StrToInt(value);
+        end;
+      tkInt64 :
+        begin
+          Result := StrToInt64(value);
+        end;
+      tkFloat :
+        begin
+          if propinfo.PropType = TypeInfo(TDateTime) then
+          begin
+            Result := JsonDateToDateTime(value);
+          end
+          else if propinfo.PropType = TypeInfo(TDate) then
+          begin
+            Result := StrToDate(value);
+          end
+          else if propinfo.PropType = TypeInfo(TTime) then
+          begin
+            Result := StrToTime(value);
+          end
+          else
+          begin
+            fsettings := DefaultFormatSettings;
+            Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
+          end;
+        end;
+      tkEnumeration:
+        begin
+          Result := value;
+        end;
+      tkBool :
+          begin
+            Result := StrToBool(value);
+          end;
+      tkSet :
+        begin
+          Result := value;
+        end;
+    else
+        begin
+          //raise EclJsonSerializerError.Create('Not supported data type!');
+        end;
+    end;
+    //if not Result.IsEmpty then SetPropertyValue(aObject,propinfo,Result);
+  except
+    on E : Exception do
+    begin
+      raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s" : %s',[aObject.ClassName,e.Message]);
+    end;
+  end;
+end;
+{$ENDIF}
 
 
 function TJsonSerializer.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
 function TJsonSerializer.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
 var
 var
   propname : string;
   propname : string;
+  cname : string;
 begin
 begin
   Result := True;
   Result := True;
   propname := aPropertyName.ToLower;
   propname := aPropertyName.ToLower;
-
-  if (aObject.ClassName.StartsWith('TObjectList')) or (aObject.ClassName.StartsWith('TList')) then
+  cname := aObject.ClassName;
+  if (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList')) then
   begin
   begin
     if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
     if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
   end
   end
@@ -577,24 +772,125 @@ begin
 end;
 end;
 
 
 function TJsonSerializer.IsGenericList(aObject : TObject) : Boolean;
 function TJsonSerializer.IsGenericList(aObject : TObject) : Boolean;
+var
+  cname : string;
+begin
+  cname := aObject.ClassName;
+  Result := (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList'));
+end;
+
+function TJsonSerializer.GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
+var
+  pinfo : PPropInfo;
 begin
 begin
-  Result := (aObject.ClassName.StartsWith('TObjectList')) or (aObject.ClassName.StartsWith('TList'));
+  Result := nil;
+  pinfo := GetPropInfo(Instance,PropertyName);
+  case pinfo.PropType^.Kind of
+    tkInteger : Result := GetOrdProp(Instance,pinfo);
+    tkInt64 : Result := GetInt64Prop(Instance,PropertyName);
+    tkFloat : Result := GetFloatProp(Instance,PropertyName);
+    tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
+    {$IFDEF FPC}
+    tkSString,
+    tkAString,
+    {$ENDIF}
+    tkLString : Result := GetStrProp(Instance,pinfo);
+    tkWString : Result := GetWideStrProp(Instance,PropertyName);
+    {$IFDEF FPC}
+    tkEnumeration : Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName));
+    {$ELSE}
+    tkEnumeration : Result := GetEnumName(@pinfo.PropType,GetOrdProp(Instance,PropertyName));
+    {$ENDIF}
+    tkSet : Result := GetSetProp(Instance,pinfo,True);
+    {$IFNDEF FPC}
+    tkClass :
+    {$ELSE}
+    tkBool : Result := Boolean(GetOrdProp(Instance,pinfo));
+    tkObject :
+    {$ENDIF} Result := GetObjectProp(Instance,pinfo);
+    tkDynArray : Result := GetDynArrayProp(Instance,pinfo);
+  end;
+end;
+
+procedure TJsonSerializer.SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue);
+var
+  pinfo : PPropInfo;
+begin
+  pinfo := GetPropInfo(Instance,PropertyName);
+  SetPropertyValue(Instance,pinfo,aValue);
+end;
+
+procedure TJsonSerializer.SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue);
+begin
+  case aPropInfo.PropType^.Kind of
+    tkInteger : SetOrdProp(Instance,aPropInfo,aValue.AsInteger);
+    tkInt64 : SetInt64Prop(Instance,aPropInfo,aValue.AsInt64);
+    tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
+    tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
+    {$IFDEF FPC}
+    tkSString,
+    tkAString,
+    {$ENDIF}
+    tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
+    tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
+    {$IFDEF FPC}
+    tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
+    tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
+    {$ENDIF}
+    tkEnumeration : SetEnumProp(Instance,aPropInfo,aValue.AsString);
+    {$IFNDEF FPC}
+    tkClass :
+    {$ELSE}
+    tkObject :
+    {$ENDIF} SetObjectProp(Instance,aPropInfo,aValue.AsObject);
+  end;
+end;
+
+{$IFDEF FPC}
+procedure TJsonSerializer.LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
+type
+  TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
+const
+  Delims = [' ', ',', '[', ']'];
+var
+  TypeInfo: PTypeInfo;
+  W: Cardinal;
+  I, N: Integer;
+  Count: Integer;
+  EnumName: string;
+begin
+  W := 0;
+  TypeInfo := GetTypeData(GetPropType(aPropInfo))^.CompType;
+  Count := WordCount(aValue, Delims);
+  for N := 1 to Count do
+  begin
+    EnumName := ExtractWord(N, aValue, Delims);
+    try
+      I := GetEnumValue(TypeInfo, EnumName);
+      if I >= 0 then Include(TCardinalSet(W),I);
+    except
+    end;
+  end;
+  SetOrdProp(aInstance,aPropInfo,W);
 end;
 end;
+{$ENDIF}
 
 
 function TJsonSerializer.Serialize(aObject: TObject): TJSONObject;
 function TJsonSerializer.Serialize(aObject: TObject): TJSONObject;
 var
 var
   ctx: TRttiContext;
   ctx: TRttiContext;
+  {$IFNDEF FPC}
   attr : TCustomAttribute;
   attr : TCustomAttribute;
+  comment : string;
+  {$ENDIF}
   rType: TRttiType;
   rType: TRttiType;
   rProp: TRttiProperty;
   rProp: TRttiProperty;
   jpair : TJSONPair;
   jpair : TJSONPair;
   ExcludeSerialize : Boolean;
   ExcludeSerialize : Boolean;
-  comment : string;
   propertyname : string;
   propertyname : string;
 
 
-  listtype : TRttiType;
-  listprop : TRttiProperty;
-  listvalue : TValue;
+  //listtype : TRttiType;
+  //listprop : TRttiProperty;
+  //listvalue : TValue;
 begin
 begin
   if (aObject = nil) then
   if (aObject = nil) then
   begin
   begin
@@ -610,8 +906,9 @@ begin
       for rProp in rType.GetProperties do
       for rProp in rType.GetProperties do
       begin
       begin
         ExcludeSerialize := False;
         ExcludeSerialize := False;
-        comment := '';
         propertyname := rProp.Name;
         propertyname := rProp.Name;
+        {$IFNDEF FPC}
+        comment := '';
         for attr in rProp.GetAttributes do
         for attr in rProp.GetAttributes do
         begin
         begin
           if attr is TNotSerializableProperty then ExcludeSerialize := True
           if attr is TNotSerializableProperty then ExcludeSerialize := True
@@ -619,13 +916,15 @@ begin
           else if  attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
           else if  attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
         end;
         end;
         if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
         if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
-            or ((fSerializeLevel = slPublishedProperty) and (IsPublishedProp(aObject,rProp.Name))) then
+            or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
+        {$ENDIF}
         begin
         begin
           if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
           if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
           begin
           begin
             //add comment as pair
             //add comment as pair
+            {$IFNDEF FPC}
             if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
             if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
-            //s := rProp.Name;
+            {$ENDIF}
             //listtype := ctx.GetType(rProp.GetValue(aObject).TypeInfo);
             //listtype := ctx.GetType(rProp.GetValue(aObject).TypeInfo);
             //if (listtype.ClassParent.ClassName.StartsWith('TObjectList')) then
             //if (listtype.ClassParent.ClassName.StartsWith('TObjectList')) then
             //begin
             //begin
@@ -642,10 +941,17 @@ begin
             //end
             //end
             //else
             //else
             begin
             begin
+              {$IFNDEF FPC}
               jpair := Serialize(propertyname,rProp.GetValue(aObject));
               jpair := Serialize(propertyname,rProp.GetValue(aObject));
+              {$ELSE}
+              jpair := Serialize(aObject,rProp.PropertyType.TypeKind,propertyname);
+              {$ENDIF}
               //s := jpair.JsonValue.ToString;
               //s := jpair.JsonValue.ToString;
-              if jpair <> nil then Result.AddPair(jpair)
-                else jpair.Free;
+              if jpair <> nil then
+              begin
+                Result.AddPair(jpair);
+              end
+              else jpair.Free;
             end;
             end;
             //Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
             //Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
             //s := Result.ToJSON;
             //s := Result.ToJSON;
@@ -669,22 +975,32 @@ begin
   TValue.Make(aAddr,aType.Handle,Result);
   TValue.Make(aAddr,aType.Handle,Result);
 end;
 end;
 
 
-function TJsonSerializer.Serialize(const aName : string; aValue : TValue): TJSONPair;
+function TJsonSerializer.GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue;
+begin
+  TValue.Make(aAddr,aTypeInfo,Result);
+end;
+
+{$IFNDEF FPC}
+function TJsonSerializer.Serialize(const aName : string; aValue : TValue) : TJSONPair;
 var
 var
   ctx: TRttiContext;
   ctx: TRttiContext;
+  {$IFNDEF FPC}
   rRec : TRttiRecordType;
   rRec : TRttiRecordType;
   rField : TRttiField;
   rField : TRttiField;
   rDynArray : TRTTIDynamicArrayType;
   rDynArray : TRTTIDynamicArrayType;
+  {$ENDIF}
   json : TJSONObject;
   json : TJSONObject;
   jArray : TJSONArray;
   jArray : TJSONArray;
   jPair : TJSONPair;
   jPair : TJSONPair;
   jValue : TJSONValue;
   jValue : TJSONValue;
   i : Integer;
   i : Integer;
+  s : string;
 begin
 begin
   Result := TJSONPair.Create(aName,nil);
   Result := TJSONPair.Create(aName,nil);
   //Result.JsonString := TJSONString(aName);
   //Result.JsonString := TJSONString(aName);
   try
   try
-    case aValue.Kind of
+    case avalue.Kind of
+      {$IFNDEF FPC}
       tkDynArray :
       tkDynArray :
         begin
         begin
           jArray := TJSONArray.Create;
           jArray := TJSONArray.Create;
@@ -708,6 +1024,7 @@ begin
             ctx.Free;
             ctx.Free;
           end;
           end;
         end;
         end;
+        {$ENDIF}
       tkClass :
       tkClass :
         begin
         begin
            Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
            Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
@@ -742,7 +1059,14 @@ begin
           begin
           begin
             Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
             Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
           end
           end
-          else Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
+          else
+          begin
+            {$IFNDEF FPC}
+            Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
+            {$ELSE}
+            Result.JsonValue := TJsonFloatNumber.Create(aValue.AsExtended);
+            {$ENDIF}
+          end;
         end;
         end;
       tkEnumeration :
       tkEnumeration :
         begin
         begin
@@ -752,14 +1076,15 @@ begin
           end
           end
           else
           else
           begin
           begin
-            Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
-            //Result.JsonValue := TJSONString.Create(aValue.ToString);
+            //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
+            Result.JsonValue := TJSONString.Create(aValue.ToString);
           end;
           end;
         end;
         end;
       tkSet :
       tkSet :
         begin
         begin
           Result.JsonValue := TJSONString.Create(aValue.ToString);
           Result.JsonValue := TJSONString.Create(aValue.ToString);
         end;
         end;
+      {$IFNDEF FPC}
       tkRecord :
       tkRecord :
         begin
         begin
           rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
           rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
@@ -774,6 +1099,7 @@ begin
             ctx.Free;
             ctx.Free;
           end;
           end;
         end;
         end;
+      {$ENDIF}
       tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
       tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
         begin
         begin
           //skip these properties
           //skip these properties
@@ -781,19 +1107,202 @@ begin
         end
         end
     else
     else
       begin
       begin
-        raise EJsonSerializeError.Create(Format(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]));
+        {$IFNDEF FPC}
+        raise EJsonSerializeError.CreateFmt(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]);
+        {$ELSE}
+        //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
+        {$ENDIF}
       end;
       end;
     end;
     end;
   except
   except
     on E : Exception do
     on E : Exception do
     begin
     begin
       Result.Free;
       Result.Free;
+      {$IFNDEF FPC}
       raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
       raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
+      {$ENDIF}
     end;
     end;
   end;
   end;
 end;
 end;
+{$ELSE}
+function TJsonSerializer.GetPropType(aPropInfo: PPropInfo): PTypeInfo;
+begin
+  Result := aPropInfo^.PropType;
+end;
 
 
+function TJsonSerializer.FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
+const
+  Precisions: array[TFloatType] of Integer = (7, 15, 18, 18, 19);
+var
+  fsettings : TFormatSettings;
+begin
+  fsettings := FormatSettings;
+  Result := StringReplace(FloatToStrF(GetFloatProp(aObject, aPropInfo), ffGeneral,
+    Precisions[GetTypeData(GetPropType(aPropInfo))^.FloatType],0),
+    '.',fsettings.DecimalSeparator,[rfReplaceAll]);
+end;
 
 
+function TJsonSerializer.Serialize(const aName : string; aValue : TValue) : TJSONPair;
+begin
+  Result := TJSONPair.Create(aName,nil);
+  //Result.JsonString := TJSONString(aName);
+  try
+    case avalue.Kind of
+      tkInteger, tkInt64 :
+        begin
+          Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
+        end;
+    else
+      begin
+        //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
+      end;
+    end;
+  except
+    Result.Free;
+  end;
+end;
+
+function TJsonSerializer.Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
+var
+  propinfo : PPropInfo;
+  jArray : TJsonArray;
+  jPair : TJsonPair;
+  jValue : TJsonValue;
+  i : Integer;
+  pArr : Pointer;
+  rValue : TValue;
+  rItemValue : TValue;
+  len : Integer;
+begin
+  try
+    Result := TJSONPair.Create(aPropertyName,nil);
+
+    propinfo := GetPropInfo(aObject,aPropertyName);
+    //case propinfo.PropType.Kind of
+    case aType of
+      tkDynArray :
+        begin
+          len := 0;
+          jArray := TJSONArray.Create;
+          try
+            pArr := GetDynArrayProp(aObject,aPropertyName);
+            TValue.Make(@pArr,propinfo.PropType, rValue);
+            if rValue.IsArray then len := rValue.GetArrayLength;
+            for i := 0 to len - 1 do
+            begin
+              rItemValue := rValue.GetArrayElement(i);
+              jPair := Serialize(aPropertyName,rItemValue);
+              try
+                //jValue := TJsonValue(jPair.JsonValue.Clone);
+                jValue := jPair.JsonValue;
+                jArray.Add(jValue);
+                //jPair.JsonValue.Owned := False;
+              finally
+                jPair.Free;
+                //jValue.Owned := True;
+              end;
+            end;
+            Result.JsonValue := jArray;
+          finally
+            DynArrayClear(pArr,propinfo.PropType);
+          end;
+        end;
+      tkClass :
+        begin
+          Result.JsonValue := TJSONValue(Serialize(GetObjectProp(aObject,aPropertyName)));
+        end;
+      tkString, tkLString, tkWString, tkUString, tkAString :
+        begin
+          Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
+        end;
+      tkChar, tkWChar :
+        begin
+          Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
+        end;
+      tkInteger :
+        begin
+          Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
+        end;
+      tkInt64 :
+        begin
+          Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
+        end;
+      tkFloat :
+        begin
+          if propinfo.PropType = TypeInfo(TDateTime) then
+          begin
+            Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
+          end
+          else if propinfo.PropType = TypeInfo(TDate) then
+          begin
+            Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
+          end
+          else if propinfo.PropType = TypeInfo(TTime) then
+          begin
+            Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
+          end
+          else
+          begin
+            //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
+            Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
+          end;
+        end;
+      tkEnumeration,tkBool :
+        begin
+          if (propinfo.PropType = System.TypeInfo(Boolean)) then
+          begin
+            Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
+          end
+          else
+          begin
+            Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)));
+            //Result.JsonValue := TJSONString.Create(aValue.ToString);
+          end;
+        end;
+      tkSet :
+        begin
+          Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
+        end;
+      {$IFNDEF FPC}
+      tkRecord :
+        begin
+          rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
+          try
+            json := TJSONObject.Create;
+            for rField in rRec.GetFields do
+            begin
+              json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
+            end;
+            Result.JsonValue := json;
+          finally
+            ctx.Free;
+          end;
+        end;
+      {$ENDIF}
+      tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
+        begin
+          //skip these properties
+          FreeAndNil(Result);
+        end
+    else
+      begin
+
+        //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
+      end;
+    end;
+  except
+    on E : Exception do
+    begin
+      Result.Free;
+      {$IFNDEF FPC}
+      raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
+      {$ENDIF}
+    end;
+  end;
+end;
+{$ENDIF}
+
+{$IFNDEF FPC}
 { TCommentProperty }
 { TCommentProperty }
 
 
 constructor TCommentProperty.Create(const aComment: string);
 constructor TCommentProperty.Create(const aComment: string);
@@ -807,6 +1316,8 @@ constructor TCustomNameProperty.Create(const aName: string);
 begin
 begin
   fName := aName;
   fName := aName;
 end;
 end;
+{$ENDIF}
+
 
 
 end.
 end.
 
 

+ 134 - 0
Quick.Json.fpc.Compatibility.pas

@@ -0,0 +1,134 @@
+unit Quick.Json.fpc.Compatibility;
+
+{$i QuickLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  fpjson,
+  jsonparser;
+
+type
+
+  TJsonPair = class
+  private
+    fJsonString : string;
+    fJsonValue : TJsonData;
+  public
+    constructor Create(const aName : string; aValue : TJsonData);
+    property JsonString : string read fJsonString write fJsonString;
+    property JsonValue : TJsonData read fJsonValue write fJsonValue;
+  end;
+
+  { TJsonArray }
+
+  TJsonArrayEx = class(fpjson.TJSONArray)
+  public
+    procedure AddElement(aValue : TJsonData);
+  end;
+
+  { TJsonObject }
+
+  TJsonObject = class(fpjson.TJsonObject)
+  private
+    function GetPair(Index : Integer): TJsonPair;
+  public
+    procedure AddPair(aValue : TJsonPair); overload;
+    procedure AddPair(const aName : TJsonStringType; aValue : TJsonData); overload;
+    class function ParseJSONValue(const JSON: string; const UseUTF8: Boolean = True): TJSONData;
+    function GetValue(const aName : string) : TJsonData;
+    function ToJson : TJSONStringType;
+    property Pairs[Index : Integer] : TJsonPair read GetPair; default;
+  end;
+
+  TJsonValue = TJsonData;
+
+  TJsonNumber = class(fpjson.TJsonIntegerNumber)
+  public
+    constructor Create(aValue : Integer); overload;
+    constructor Create(aValue : Extended); overload;
+  end;
+
+  TJsonString = class(fpjson.TJsonString)
+  public
+    constructor Create(const aValue : string); overload;
+  end;
+
+  TJsonBool = class(fpjson.TJSONBoolean)
+  public
+    constructor Create(aValue : Boolean);
+  end;
+
+implementation
+
+{ TJsonArray }
+
+procedure TJsonArrayEx.AddElement(aValue: TJsonData);
+begin
+  Add(aValue);
+end;
+
+function TJsonObject.GetPair(Index : Integer): TJsonPair;
+begin
+  Result := TJsonPair.Create(Self.Names[Index],Self.Items[Index]);
+end;
+
+procedure TJsonObject.AddPair(aValue : TJsonPair);
+begin
+  Add(aValue.JsonString,aValue.JsonValue);
+end;
+
+procedure TJsonObject.AddPair(const aName: TJsonStringType; aValue: TJsonData);
+begin
+  Add(aName,aValue);
+end;
+
+class function TJsonObject.ParseJSONValue(const JSON: string; const UseUTF8: Boolean = True): TJSONData;
+begin
+  Result := GetJson(JSON,UseUTF8);
+end;
+
+function TJsonObject.ToJson : TJSONStringType;
+begin
+  try
+    Result := AsJson;
+  except
+    raise Exception.Create('Json not valid');
+  end;
+end;
+
+function TJsonObject.GetValue(const aName : string) : TJsonData;
+begin
+  Result := Find(aName);
+end;
+
+constructor TJsonPair.Create(const aName : string; aValue : TJsonData);
+begin
+  fJsonString := aName;
+  fJsonValue := aValue;
+end;
+
+constructor TJsonNumber.Create(aValue : Integer);
+begin
+  inherited Create(aValue);
+end;
+
+constructor TJsonNumber.Create(aValue : Extended);
+begin
+  Create(aValue);
+end;
+
+constructor TJsonBool.Create(aValue : Boolean);
+begin
+  inherited Create(aValue);
+end;
+
+constructor TJsonString.Create(const aValue : string);
+begin
+  inherited Create(aValue);
+end;
+
+end.
+

+ 24 - 13
samples/delphi/QuickConfig/ConfigToFileAndRegistry/Main.pas

@@ -44,19 +44,27 @@ type
     fTitle : string;
     fTitle : string;
     fHidden : Boolean;
     fHidden : Boolean;
     fSessionName: string;
     fSessionName: string;
+    fSizes : TArray<Integer>;
+    fLastFilename : string;
+    fWindowPos : TWinPos;
+    fHistory : TArray<TProcessType>;
+    fComplex : TProcessType;
+    fModifyDate : TDateTime;
+    fWorkList : TObjectList<TWorker>;
+  published
+    property Sizes : TArray<Integer> read fSizes write fSizes;
+    property LastFilename : string read fLastFilename write fLastFilename;
+    property WindowPos : TWinPos read fWindowPos write fWindowPos;
+    property History : TArray<TProcessType> read fHistory write fHistory;
+    property Complex : TProcessType read fComplex write fComplex;
+    property ModifyDate : TDateTime read fModifyDate write fModifyDate;
+    property Title : string read fTitle write fTitle;
+    property SessionName : string read fSessionName write fSessionName;
   public
   public
-    Sizes : array of Integer;
-    LastFilename : string;
-    WindowPos : TWinPos;
-    History : array of TProcessType;
-    Complex : TProcessType;
-    ModifyDate : TDateTime;
-    WorkList : TObjectList<TWorker>;
+    property WorkList : TObjectList<TWorker> read fWorkList write fWorkList;
     constructor Create; override;
     constructor Create; override;
     destructor Destroy; override;
     destructor Destroy; override;
     procedure DefaultValues;
     procedure DefaultValues;
-    property Title : string read fTitle write fTitle;
-    property SessionName : string read fSessionName write fSessionName;
   end;
   end;
 
 
   TMainForm = class(TForm)
   TMainForm = class(TForm)
@@ -119,16 +127,19 @@ end;
 
 
 procedure TMainForm.SetConfig(cConfig : TMyConfig);
 procedure TMainForm.SetConfig(cConfig : TMyConfig);
 var
 var
+  winpos : TWinpos;
   protype : TProcessType;
   protype : TProcessType;
   i : Integer;
   i : Integer;
   worker : TWorker;
   worker : TWorker;
 begin
 begin
   cConfig.LastFilename := 'library.txt';
   cConfig.LastFilename := 'library.txt';
   cConfig.Sizes := [23,11,554,12,34,29,77,30,48,59,773,221,98,3,22,983,122,231,433,12,31,987];
   cConfig.Sizes := [23,11,554,12,34,29,77,30,48,59,773,221,98,3,22,983,122,231,433,12,31,987];
-  cConfig.WindowPos.PosX := 640;
-  cConfig.WindowPos.PosX := 480;
-  cConfig.Complex.Priority := msHigh;
-  cConfig.Complex.Redundant := False;
+  winpos.PosX := 640;
+  winpos.PosX := 480;
+  cConfig.WindowPos := winpos;
+  protype.Priority := msHigh;
+  protype.Redundant := False;
+  cConfig.Complex := protype;
   cConfig.Title := 'a fresh title';
   cConfig.Title := 'a fresh title';
   cConfig.SessionName := 'First Session';
   cConfig.SessionName := 'First Session';
   for I := 0 to 22 do
   for I := 0 to 22 do

+ 1 - 551
samples/delphi/QuickConfig/ConfigToFileAndRegistry/Win64/Debug/Config.json

@@ -1,551 +1 @@
-{
-  "Sizes": [
-    23,
-    11,
-    554,
-    12,
-    34,
-    29,
-    77,
-    30,
-    48,
-    59,
-    773,
-    221,
-    98,
-    3,
-    22,
-    983,
-    122,
-    231,
-    433,
-    12,
-    31,
-    987
-  ],
-  "LastFilename": "library.txt",
-  "WindowPos": {
-    "PosX": 480,
-    "PosY": 0
-  },
-  "History": [
-    {
-      "Id": 0,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 1,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 2,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 3,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 4,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 5,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 6,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 7,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 8,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 9,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 10,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 11,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 12,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 13,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 14,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 15,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 0,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 1,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 2,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 3,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 4,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 5,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 6,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 7,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 8,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 9,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 10,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 11,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 12,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 13,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 14,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 15,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 0,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 1,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 2,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 3,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 4,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 5,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 6,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 7,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 8,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 9,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 10,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 11,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 12,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 13,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 14,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 15,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 0,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 1,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 2,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 3,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 4,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 5,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 6,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 7,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 8,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 9,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 10,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 11,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 12,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 13,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 14,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 15,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 0,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 1,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 2,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 3,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 4,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 5,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 6,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 7,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 8,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 9,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 10,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 11,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 12,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 13,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 14,
-      "Priority": 0,
-      "Redundant": true
-    },
-    {
-      "Id": 15,
-      "Priority": 0,
-      "Redundant": true
-    }
-  ],
-  "Complex": {
-    "Id": 0,
-    "Priority": 2,
-    "Redundant": false
-  },
-  "ModifyDate": "11/11/2017 16:37:39",
-  "WorkList": {
-    "FOwnsObjects": true,
-    "FListHelper": {
-      "FCount": 23
-    },
-    "FItems": [
-      {
-        "Name": "Process 0",
-        "Active": false
-      },
-      {
-        "Name": "Process 1",
-        "Active": false
-      },
-      {
-        "Name": "Process 2",
-        "Active": false
-      },
-      {
-        "Name": "Process 3",
-        "Active": false
-      },
-      {
-        "Name": "Process 4",
-        "Active": false
-      },
-      {
-        "Name": "Process 5",
-        "Active": false
-      },
-      {
-        "Name": "Process 6",
-        "Active": false
-      },
-      {
-        "Name": "Process 7",
-        "Active": false
-      },
-      {
-        "Name": "Process 8",
-        "Active": false
-      },
-      {
-        "Name": "Process 9",
-        "Active": false
-      },
-      {
-        "Name": "Process 10",
-        "Active": false
-      },
-      {
-        "Name": "Process 11",
-        "Active": false
-      },
-      {
-        "Name": "Process 12",
-        "Active": false
-      },
-      {
-        "Name": "Process 13",
-        "Active": false
-      },
-      {
-        "Name": "Process 14",
-        "Active": false
-      },
-      {
-        "Name": "Process 15",
-        "Active": false
-      },
-      {
-        "Name": "Process 16",
-        "Active": false
-      },
-      {
-        "Name": "Process 17",
-        "Active": false
-      },
-      {
-        "Name": "Process 18",
-        "Active": false
-      },
-      {
-        "Name": "Process 19",
-        "Active": false
-      },
-      {
-        "Name": "Process 20",
-        "Active": false
-      },
-      {
-        "Name": "Process 21",
-        "Active": false
-      },
-      {
-        "Name": "Process 22",
-        "Active": false
-      },
-      null,
-      null,
-      null,
-      null,
-      null,
-      null,
-      null,
-      null,
-      null
-    ],
-    "FComparer": {}
-  },
-  "Title": "a fresh title",
-  "SessionName": "First Session"
-}
+{"Sizes":[23,11,554,12,34,29,77,30,48,59,773,221,98,3,22,983,122,231,433,12,31,987],"LastFilename":"library.txt","WindowPos":{"PosX":480,"PosY":0},"History":[{"Id":0,"Priority":"msLow","Redundant":true},{"Id":1,"Priority":"msLow","Redundant":true},{"Id":2,"Priority":"msLow","Redundant":true},{"Id":3,"Priority":"msLow","Redundant":true},{"Id":4,"Priority":"msLow","Redundant":true},{"Id":5,"Priority":"msLow","Redundant":true},{"Id":6,"Priority":"msLow","Redundant":true},{"Id":7,"Priority":"msLow","Redundant":true},{"Id":8,"Priority":"msLow","Redundant":true},{"Id":9,"Priority":"msLow","Redundant":true},{"Id":10,"Priority":"msLow","Redundant":true},{"Id":11,"Priority":"msLow","Redundant":true},{"Id":12,"Priority":"msLow","Redundant":true},{"Id":13,"Priority":"msLow","Redundant":true},{"Id":14,"Priority":"msLow","Redundant":true},{"Id":15,"Priority":"msLow","Redundant":true}],"Complex":{"Id":88586818,"Priority":"msHigh","Redundant":false},"ModifyDate":"2018-07-17T14:38:51.937Z","Title":"a fresh title","SessionName":"First Session"}

+ 17 - 0
samples/delphi/QuickJsonSerializer/JsonSerializer.dpr

@@ -0,0 +1,17 @@
+program JsonSerializer;
+
+uses
+  System.StartUpCopy,
+  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';
+
+{$R *.res}
+
+begin
+  ReportMemoryLeaksOnShutdown := True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.

+ 289 - 0
samples/delphi/QuickJsonSerializer/JsonSerializer.dproj

@@ -0,0 +1,289 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <ProjectGuid>{9C6576EF-31E8-4604-A9A1-B9FAC5DBF05A}</ProjectGuid>
+        <MainSource>JsonSerializer.dpr</MainSource>
+        <Base>True</Base>
+        <Config Condition="'$(Config)'==''">Debug</Config>
+        <TargetedPlatforms>1025</TargetedPlatforms>
+        <AppType>Application</AppType>
+        <FrameworkType>FMX</FrameworkType>
+        <ProjectVersion>18.4</ProjectVersion>
+        <Platform Condition="'$(Platform)'==''">Win32</Platform>
+    </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)'=='Release' 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)'=='Debug' or '$(Cfg_2)'!=''">
+        <Cfg_2>true</Cfg_2>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice32' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSDevice32)'!=''">
+        <Cfg_2_iOSDevice32>true</Cfg_2_iOSDevice32>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSDevice64)'!=''">
+        <Cfg_2_iOSDevice64>true</Cfg_2_iOSDevice64>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='iOSSimulator' and '$(Cfg_2)'=='true') or '$(Cfg_2_iOSSimulator)'!=''">
+        <Cfg_2_iOSSimulator>true</Cfg_2_iOSSimulator>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='OSX32' and '$(Cfg_2)'=='true') or '$(Cfg_2_OSX32)'!=''">
+        <Cfg_2_OSX32>true</Cfg_2_OSX32>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
+        <Cfg_2_Win32>true</Cfg_2_Win32>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base)'!=''">
+        <DCC_E>false</DCC_E>
+        <DCC_F>false</DCC_F>
+        <DCC_K>false</DCC_K>
+        <DCC_N>false</DCC_N>
+        <DCC_S>false</DCC_S>
+        <DCC_ImageBase>00400000</DCC_ImageBase>
+        <SanitizedProjectName>JsonSerializer</SanitizedProjectName>
+        <VerInfo_Locale>3082</VerInfo_Locale>
+        <VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=</VerInfo_Keys>
+        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
+        <Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
+        <Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Android)'!=''">
+        <VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <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>
+        <AUP_ACCESS_COARSE_LOCATION>true</AUP_ACCESS_COARSE_LOCATION>
+        <AUP_ACCESS_FINE_LOCATION>true</AUP_ACCESS_FINE_LOCATION>
+        <AUP_CALL_PHONE>true</AUP_CALL_PHONE>
+        <AUP_CAMERA>true</AUP_CAMERA>
+        <AUP_INTERNET>true</AUP_INTERNET>
+        <AUP_READ_CALENDAR>true</AUP_READ_CALENDAR>
+        <AUP_READ_EXTERNAL_STORAGE>true</AUP_READ_EXTERNAL_STORAGE>
+        <AUP_WRITE_CALENDAR>true</AUP_WRITE_CALENDAR>
+        <AUP_WRITE_EXTERNAL_STORAGE>true</AUP_WRITE_EXTERNAL_STORAGE>
+        <AUP_READ_PHONE_STATE>true</AUP_READ_PHONE_STATE>
+        <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)'!=''">
+        <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone &amp; iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera</VerInfo_Keys>
+        <VerInfo_UIDeviceFamily>iPhoneAndiPad</VerInfo_UIDeviceFamily>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_BundleId>$(MSBuildProjectName)</VerInfo_BundleId>
+        <iPhone_AppIcon60>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png</iPhone_AppIcon60>
+        <iPhone_AppIcon120>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png</iPhone_AppIcon120>
+        <iPhone_Spotlight40>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png</iPhone_Spotlight40>
+        <iPhone_Spotlight80>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png</iPhone_Spotlight80>
+        <iPad_SpotLight40>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png</iPad_SpotLight40>
+        <iPad_SpotLight80>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png</iPad_SpotLight80>
+        <iPad_AppIcon76>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png</iPad_AppIcon76>
+        <iPad_AppIcon152>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png</iPad_AppIcon152>
+        <iPad_Launch768x1024>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png</iPad_Launch768x1024>
+        <iPad_Launch1024x768>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png</iPad_Launch1024x768>
+        <iPad_Launch1536x2048>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png</iPad_Launch1536x2048>
+        <iPad_Launch2048x1536>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png</iPad_Launch2048x1536>
+        <iPhone_AppIcon87>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_87x87.png</iPhone_AppIcon87>
+        <iPhone_AppIcon180>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png</iPhone_AppIcon180>
+        <iPhone_Launch750>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_750x1334.png</iPhone_Launch750>
+        <iPhone_Launch1242>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1242x2208.png</iPhone_Launch1242>
+        <iPhone_Launch2208>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2208x1242.png</iPhone_Launch2208>
+        <iPhone_Launch1125>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1125x2436.png</iPhone_Launch1125>
+        <iPhone_Launch2436>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2436x1125.png</iPhone_Launch2436>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSDevice64)'!=''">
+        <iPhone_AppIcon87>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_87x87.png</iPhone_AppIcon87>
+        <iPhone_AppIcon180>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png</iPhone_AppIcon180>
+        <iPhone_Launch750>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_750x1334.png</iPhone_Launch750>
+        <iPhone_Launch1242>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1242x2208.png</iPhone_Launch1242>
+        <iPhone_Launch2208>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2208x1242.png</iPhone_Launch2208>
+        <iPhone_Launch1125>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1125x2436.png</iPhone_Launch1125>
+        <iPhone_Launch2436>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2436x1125.png</iPhone_Launch2436>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_iOSSimulator)'!=''">
+        <VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone &amp; iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera</VerInfo_Keys>
+        <VerInfo_UIDeviceFamily>iPhoneAndiPad</VerInfo_UIDeviceFamily>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <iPhone_AppIcon60>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png</iPhone_AppIcon60>
+        <iPhone_AppIcon120>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png</iPhone_AppIcon120>
+        <iPhone_Spotlight40>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png</iPhone_Spotlight40>
+        <iPhone_Spotlight80>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png</iPhone_Spotlight80>
+        <iPad_SpotLight40>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png</iPad_SpotLight40>
+        <iPad_SpotLight80>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png</iPad_SpotLight80>
+        <iPad_AppIcon76>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png</iPad_AppIcon76>
+        <iPad_AppIcon152>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png</iPad_AppIcon152>
+        <iPad_Launch768x1024>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png</iPad_Launch768x1024>
+        <iPad_Launch1024x768>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png</iPad_Launch1024x768>
+        <iPad_Launch1536x2048>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png</iPad_Launch1536x2048>
+        <iPad_Launch2048x1536>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png</iPad_Launch2048x1536>
+        <iPhone_AppIcon87>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_87x87.png</iPhone_AppIcon87>
+        <iPhone_AppIcon180>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png</iPhone_AppIcon180>
+        <iPhone_Launch750>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_750x1334.png</iPhone_Launch750>
+        <iPhone_Launch1242>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1242x2208.png</iPhone_Launch1242>
+        <iPhone_Launch2208>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2208x1242.png</iPhone_Launch2208>
+        <iPhone_Launch1125>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_1125x2436.png</iPhone_Launch1125>
+        <iPhone_Launch2436>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2436x1125.png</iPhone_Launch2436>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_OSX32)'!=''">
+        <Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win32)'!=''">
+        <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_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <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)'!=''">
+        <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>RELEASE;$(DCC_Define)</DCC_Define>
+        <DCC_DebugInformation>0</DCC_DebugInformation>
+        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppEnableHighDPI>true</AppEnableHighDPI>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2)'!=''">
+        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+        <DCC_Optimize>false</DCC_Optimize>
+        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_iOSDevice32)'!=''">
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_iOSDevice64)'!=''">
+        <BT_BuildType>Debug</BT_BuildType>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_iOSSimulator)'!=''">
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_OSX32)'!=''">
+        <Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppEnableHighDPI>true</AppEnableHighDPI>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)</VerInfo_Keys>
+    </PropertyGroup>
+    <ItemGroup>
+        <DelphiCompile Include="$(MainSource)">
+            <MainSource>MainSource</MainSource>
+        </DelphiCompile>
+        <DCCReference Include="C:\Users\Kike\Documents\Embarcadero\Studio\Projects\JsonUtilsTest\main.pas">
+            <Form>Form1</Form>
+        </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">
+            <Key>Cfg_2</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Base">
+            <Key>Base</Key>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Release">
+            <Key>Cfg_1</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+    </ItemGroup>
+    <ProjectExtensions>
+        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
+        <Borland.ProjectType/>
+        <BorlandProject>
+            <Delphi.Personality>
+                <Source>
+                    <Source Name="MainSource">JsonSerializer.dpr</Source>
+                </Source>
+            </Delphi.Personality>
+            <Platforms>
+                <Platform value="Android">False</Platform>
+                <Platform value="iOSDevice32">False</Platform>
+                <Platform value="iOSDevice64">True</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')"/>
+</Project>

BIN
samples/delphi/QuickJsonSerializer/JsonSerializer.res


+ 43 - 0
samples/delphi/QuickJsonSerializer/frmMain.fmx

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

+ 236 - 0
samples/delphi/QuickJsonSerializer/frmMain.pas

@@ -0,0 +1,236 @@
+unit frmMain;
+
+interface
+
+uses
+  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
+  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
+  FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.StdCtrls, Quick.Json.Serializer,
+  System.Generics.Collections;
+
+type
+
+  TID = Int64;
+
+  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;
+  public
+    property Id : TID read fId write fId;
+    property GType : TGroupType read fGType write fGType;
+  end;
+
+  TOptions = class
+  private
+    fOption1 : Integer;
+    fOption2 : string;
+    fAllowGroups : TGroupType;
+  public
+    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;
+    Contacts : TContactIdArray;
+  end;
+
+  TConnectionArray = array of TConnectionInfo;
+
+  TGroupList = TObjectList<TGroup>;
+  //TGroupList = class(TObjectList<TGroup>);
+
+  TWorkingTime = class
+  private
+    fWorkDays : TDays;
+    fFreeDays : TDays;
+  public
+    property WorkDays : TDays read fWorkDays write fWorkDays;
+    property FreeDays : TDays read fFreeDays write fFreeDays;
+  end;
+
+  TLevelPrivilege = array of TID;
+
+  TUser = class
+  private
+    fId : TID;
+    fName : string;
+    fSurname : string;
+    fAge : Integer;
+    fAddress : string;
+    fOptions : TOptions;
+    fLastConnections : TConnectionArray;
+    fMarried : Boolean;
+    fWorkingTime : TWorkingTime;
+    [TCommentProperty('gnFemale or gnMale')]
+    fGenre : TGenre;
+    fHireDate : TDateTime;
+    fLevelPrivilege : TLevelPrivilege;
+    fObservations : string;
+    fStatus : TUserStatus;
+    fGroups : TGroupList;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    [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;
+    property Address : string read fAddress write fAddress;
+    [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;
+  UserList : TUserList;
+
+implementation
+
+{$R *.fmx}
+
+procedure TForm1.btnFromJsonClick(Sender: TObject);
+var
+  newuser : TUser;
+begin
+  newuser := TUser.Create;
+  try
+    newuser := serializer.JsonToObject(newuser,Memo1.Text) as TUser;
+    //newuser.Groups := serializer.JsonToObject(newuser.Groups,Memo1.Text) as TGroupList;
+    Memo1.Lines.Add('NewUser:');
+    Memo1.Lines.Add(serializer.ObjectToJson(newuser));
+    Memo1.Lines.Add('TGroup OwnsObjects: ' + BoolToStr(newuser.Groups.OwnsObjects,True));
+    Memo1.Lines.Add('TGroup Capacity: ' + newuser.Groups.Capacity.ToString);
+    Memo1.Lines.Add('TGroup Count: ' + newuser.Groups.Count.ToString);
+    Memo1.Lines.Add(newuser.Groups[0].Id.ToString);
+    //Memo1.Lines.Add(serializer.ObjectToJson(newuser.Groups));
+  finally
+    newuser.Free;
+  end;
+end;
+
+procedure TForm1.btnToJsonClick(Sender: TObject);
+begin
+  Memo1.Text := serializer.ObjectToJson(User);
+  btnFromJson.Enabled := True;
+end;
+
+procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  User.Free;
+  serializer.Free;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+var
+  lastcon : TConnectionInfo;
+  group : TGroup;
+begin
+  serializer := TJsonSerializer.Create(slPublicProperty);
+  user := TUser.Create;
+  user.Id := 77;
+  user.Name := 'Joe';
+  user.Surname := 'Smith';
+  user.Age := 30;
+  user.Married := True;
+  user.Address := 'Sunset st. 2';
+  user.Options.Option1 := 1;
+  user.Options.Option2 := 'good';
+  user.Options.AllowGroups := gtExternal;
+  user.HireDate := Now();
+  user.LevelPrivilege := [1,2,3,4];
+  user.WorkingTime.WorkDays := DEF_WORKDAYS;
+  user.WorkingTime.FreeDays := DEF_WEEKEND;
+  user.Observations := 'Good aptitude';
+  user.Status := TUserStatus.usOnVacation;
+  lastcon.IP := '127.0.0.1';
+  lastcon.ConnectionDate := Now();
+  lastcon.Contacts := [1,2,3,4,5];
+  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.

+ 1 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/QuickConfig.lpi

@@ -47,6 +47,7 @@
         <Filename Value="umain.pas"/>
         <Filename Value="umain.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="Form1"/>
         <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
         <UnitName Value="uMain"/>
         <UnitName Value="uMain"/>
       </Unit2>
       </Unit2>

+ 1 - 0
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/QuickConfig.lpi

@@ -47,6 +47,7 @@
         <Filename Value="umain.pas"/>
         <Filename Value="umain.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
         <ComponentName Value="Form1"/>
         <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
         <ResourceBaseClass Value="Form"/>
         <ResourceBaseClass Value="Form"/>
         <UnitName Value="uMain"/>
         <UnitName Value="uMain"/>
       </Unit2>
       </Unit2>

+ 24 - 6
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.lfm

@@ -1,28 +1,28 @@
 object Form1: TForm1
 object Form1: TForm1
   Left = 379
   Left = 379
-  Height = 433
+  Height = 457
   Top = 229
   Top = 229
   Width = 592
   Width = 592
   Caption = 'Form1'
   Caption = 'Form1'
-  ClientHeight = 433
+  ClientHeight = 457
   ClientWidth = 592
   ClientWidth = 592
   OnClose = FormClose
   OnClose = FormClose
   OnCreate = FormCreate
   OnCreate = FormCreate
   LCLVersion = '1.9.0.0'
   LCLVersion = '1.9.0.0'
   object btnSaveJson: TButton
   object btnSaveJson: TButton
-    Left = 456
+    Left = 448
     Height = 25
     Height = 25
     Top = 384
     Top = 384
-    Width = 107
+    Width = 120
     Caption = 'Save to Json'
     Caption = 'Save to Json'
     OnClick = btnSaveJsonClick
     OnClick = btnSaveJsonClick
     TabOrder = 0
     TabOrder = 0
   end
   end
   object btnLoadJson: TButton
   object btnLoadJson: TButton
-    Left = 336
+    Left = 312
     Height = 25
     Height = 25
     Top = 384
     Top = 384
-    Width = 107
+    Width = 123
     Caption = 'Load From Json'
     Caption = 'Load From Json'
     OnClick = btnLoadJsonClick
     OnClick = btnLoadJsonClick
     TabOrder = 1
     TabOrder = 1
@@ -36,4 +36,22 @@ object Form1: TForm1
     ScrollBars = ssAutoBoth
     ScrollBars = ssAutoBoth
     TabOrder = 2
     TabOrder = 2
   end
   end
+  object btnSaveRegistry: TButton
+    Left = 448
+    Height = 25
+    Top = 416
+    Width = 120
+    Caption = 'Save to Registry'
+    OnClick = btnSaveRegistryClick
+    TabOrder = 3
+  end
+  object btnLoadRegistry: TButton
+    Left = 312
+    Height = 25
+    Top = 416
+    Width = 123
+    Caption = 'Load From Registry'
+    OnClick = btnLoadRegistryClick
+    TabOrder = 4
+  end
 end
 end

+ 101 - 40
samples/fpc/QuickConfig/ConfigToFileAndRegistry/backup/umain.pas

@@ -7,65 +7,92 @@ interface
 uses
 uses
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Quick.Config,
   Quick.Config,
-  //Quick.Config.Provider.Registry,
+  Quick.Config.Provider.Registry,
   Generics.Collections,
   Generics.Collections,
+  registry,
   Quick.Config.Provider.Json;
   Quick.Config.Provider.Json;
 
 
 type
 type
 
 
   TMyPriority = (msLow, msMed, msHigh);
   TMyPriority = (msLow, msMed, msHigh);
 
 
-  TWinPos = record
-    PosX : Integer;
-    PosY : Integer;
+  TWinPos = class
+  private
+    fPosX : Integer;
+    fPosY : Integer;
+  published
+    property PosX : Integer read fPosX write fPosX;
+    property PosY : Integer read fPosY write fPosY;
   end;
   end;
 
 
-  TProcessType = record
-    Id : Integer;
-    Priority : TMyPriority;
-    Redundant : Boolean;
+  TProcessType = class
+  private
+    fId : Integer;
+    fPriority : TMyPriority;
+    fRedundant : Boolean;
+  published
+    property Id : Integer read fId write fId;
+    property Priority : TMyPriority read fPriority write fPriority;
+    property Redundant : Boolean read fRedundant write fRedundant;
   end;
   end;
 
 
   TWorker = class
   TWorker = class
-    Name : string;
-    Active : Boolean;
+  private
+    fName : string;
+    fActive : Boolean;
+  published
+    property Name : string read fName write fName;
+    property Active : Boolean read fActive write fActive;
   end;
   end;
 
 
-  {$M+} TMyConfig2 = class(TAppConfig)
+  TMyConfig2 = class(TAppConfig)
   private
   private
     fhola : Integer;
     fhola : Integer;
   published
   published
     property hola : Integer read fhola write fhola;
     property hola : Integer read fhola write fhola;
   end;
   end;
 
 
-  {$M+} TMyConfig = class(TAppConfig)
+  TMyConfig = class(TAppConfig)
   private
   private
     fTitle : string;
     fTitle : string;
     fHidden : Boolean;
     fHidden : Boolean;
     fSessionName: string;
     fSessionName: string;
+    fSizes : TArray<Integer>;
+    fLastFilename : string;
+    fWindowPos : TWinPos;
+    fHistory : TArray<TProcessType>;
+    fComplex : TProcessType;
+    fModifyDate : TDateTime;
+    fWorkList : TObjectList<TWorker>;
   public
   public
-    Sizes : array of Integer;
-    LastFilename : string;
-    WindowPos : TWinPos;
-    History : array of TProcessType;
-    Complex : TProcessType;
-    ModifyDate : TDateTime;
-    WorkList : TObjectList<TWorker>;
     constructor Create; override;
     constructor Create; override;
     destructor Destroy; override;
     destructor Destroy; override;
     procedure DefaultValues;
     procedure DefaultValues;
+    property Hidden : Boolean read fHidden write fHidden;
+  published
     property Title : string read fTitle write fTitle;
     property Title : string read fTitle write fTitle;
     property SessionName : string read fSessionName write fSessionName;
     property SessionName : string read fSessionName write fSessionName;
+    property Sizes : TArray<Integer> read fSizes write fSizes;
+    property LastFilename : string read fLastFilename write fLastFilename;
+    //property WindowPos : TWinPos read fWindowPos write fWindowPos;
+    property History : TArray<TProcessType> read fHistory write fHistory;
+    property Complex : TProcessType read fComplex write fComplex;
+    property ModifyDate : TDateTime read fModifyDate write fModifyDate;
+    //property WorkList : TObjectList<TWorker> read fWorkList write fWorkList;
   end;
   end;
 
 
   { TForm1 }
   { TForm1 }
 
 
   TForm1 = class(TForm)
   TForm1 = class(TForm)
+    btnLoadRegistry: TButton;
     btnSaveJson: TButton;
     btnSaveJson: TButton;
     btnLoadJson: TButton;
     btnLoadJson: TButton;
+    btnSaveRegistry: TButton;
     meInfo: TMemo;
     meInfo: TMemo;
     procedure btnLoadJsonClick(Sender: TObject);
     procedure btnLoadJsonClick(Sender: TObject);
+    procedure btnLoadRegistryClick(Sender: TObject);
     procedure btnSaveJsonClick(Sender: TObject);
     procedure btnSaveJsonClick(Sender: TObject);
+    procedure btnSaveRegistryClick(Sender: TObject);
     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
   private
   private
@@ -79,29 +106,50 @@ type
 var
 var
   Form1: TForm1;
   Form1: TForm1;
   ConfigJson : TMyConfig;
   ConfigJson : TMyConfig;
-  ConfigJson2 : TMyConfig2;
   ConfigReg : TMyConfig;
   ConfigReg : TMyConfig;
   ConfigTest : TMyConfig;
   ConfigTest : TMyConfig;
-  AppConfigJson : TAppConfigJsonProvider<TMyConfig2>;
-  //AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
+  AppConfigJson : TAppConfigJsonProvider<TMyConfig>;
+  AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
 
 
 implementation
 implementation
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
+uses
+  Quick.Json.Serializer;
+
 { TForm1 }
 { TForm1 }
 
 
 procedure TForm1.btnSaveJsonClick(Sender: TObject);
 procedure TForm1.btnSaveJsonClick(Sender: TObject);
 begin
 begin
   SetConfig(ConfigJson);
   SetConfig(ConfigJson);
-  AppConfigJson.Save(ConfigJson2);
+  AppConfigJson.Save(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJson);
   meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
   meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
 end;
 end;
 
 
+procedure TForm1.btnSaveRegistryClick(Sender: TObject);
+begin
+  SetConfig(ConfigJson);
+  AppConfigReg.Save(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJson);
+  meInfo.Lines.Add('Saved Config in Registry at ' + DateTimeToStr(ConfigJson.LastSaved));
+end;
+
 procedure TForm1.btnLoadJsonClick(Sender: TObject);
 procedure TForm1.btnLoadJsonClick(Sender: TObject);
 begin
 begin
   meInfo.Lines.Add('Load ConfigJson');
   meInfo.Lines.Add('Load ConfigJson');
-  AppConfigJson.Load(ConfigJson2);
+  ConfigJson := TMyConfig.Create;
+  AppConfigJson.Load(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJSON);
+  if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
+end;
+
+procedure TForm1.btnLoadRegistryClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigRegistry');
+  ConfigJson := TMyConfig.Create;
+  AppConfigReg.Load(ConfigJson);
   meInfo.Lines.Add(ConfigJson.ToJSON);
   meInfo.Lines.Add(ConfigJson.ToJSON);
   if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
   if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
 end;
 end;
@@ -114,16 +162,16 @@ begin
     Assert(cConfig1.LastFilename = cConfig2.LastFilename);
     Assert(cConfig1.LastFilename = cConfig2.LastFilename);
     for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
     for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
       Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
       Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
-    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
-    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    //Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    //Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
     Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
     Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
     Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
     Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
     Assert(cConfig1.Title = cConfig2.Title);
     Assert(cConfig1.Title = cConfig2.Title);
-    for i := 0 to cConfig1.WorkList.Count - 1 do
-    begin
-      Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
-      Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
-    end;
+    //for i := 0 to cConfig1.WorkList.Count - 1 do
+    //begin
+    //  Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
+    //  Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
+    //end;
     for i := 0 to High(cConfig1.History) do
     for i := 0 to High(cConfig1.History) do
     begin
     begin
       Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
       Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
@@ -139,7 +187,7 @@ end;
 procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
 begin
   if Assigned(AppConfigJson) then AppConfigJson.Free;
   if Assigned(AppConfigJson) then AppConfigJson.Free;
-  //if Assigned(AppConfigReg) then AppConfigReg.Free;
+  if Assigned(AppConfigReg) then AppConfigReg.Free;
   if Assigned(ConfigTest) then ConfigTest.Free;
   if Assigned(ConfigTest) then ConfigTest.Free;
   if Assigned(ConfigReg) then ConfigReg.Free;
   if Assigned(ConfigReg) then ConfigReg.Free;
   if Assigned(ConfigJson) then ConfigJson.Free;
   if Assigned(ConfigJson) then ConfigJson.Free;
@@ -149,17 +197,30 @@ procedure TForm1.FormCreate(Sender: TObject);
 begin
 begin
   ConfigTest := TMyConfig.Create;
   ConfigTest := TMyConfig.Create;
   SetConfig(ConfigTest);
   SetConfig(ConfigTest);
-  AppConfigJson := TAppConfigJsonProvider<TMyConfig2>.Create(ConfigJson2);
+  AppConfigJson := TAppConfigJsonProvider<TMyConfig>.Create(ConfigJson);
   AppConfigJson.CreateIfNotExists := True;
   AppConfigJson.CreateIfNotExists := True;
-  AppConfigJson.Filename := 'Config.json';
-  //AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
-  //AppConfigReg.HRoot := HKEY_CURRENT_USER;
-  //AppConfigReg.MainKey := '_AppConfig';
+  AppConfigJson.Filename := '.\Config.json';
+  ConfigJson := TMyConfig.Create;
+  AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
+  AppConfigReg.HRoot := HKEY_CURRENT_USER;
+  AppConfigReg.MainKey := '_AppConfig';
 end;
 end;
 
 
 procedure TForm1.SetConfig(cConfig: TMyConfig);
 procedure TForm1.SetConfig(cConfig: TMyConfig);
+var
+  processtype : TProcessType;
 begin
 begin
-
+  cConfig.Title := 'hola';
+  cConfig.Complex := TProcessType.Create;
+  cConfig.Complex.Id := 1;
+  cConfig.Complex.Redundant := True;
+  cConfig.Complex.Priority := TMyPriority.msMed;
+  //processtype := TProcessType.Create;
+  //processtype.Id := 1;
+  //processtype.Priority := msLow;
+  //processtype.Redundant := True;
+  //cConfig.History := [processtype];
+  cConfig.ModifyDate := Now();
 end;
 end;
 
 
 { TMyConfig }
 { TMyConfig }
@@ -167,7 +228,7 @@ end;
 constructor TMyConfig.Create;
 constructor TMyConfig.Create;
 begin
 begin
   inherited;
   inherited;
-  WorkList := TObjectList<TWorker>.Create(True);
+  //WorkList := TObjectList<TWorker>.Create(True);
   DefaultValues;
   DefaultValues;
 end;
 end;
 
 
@@ -178,7 +239,7 @@ end;
 
 
 destructor TMyConfig.Destroy;
 destructor TMyConfig.Destroy;
 begin
 begin
-  if Assigned(WorkList) then WorkList.Free;
+  //if Assigned(WorkList) then WorkList.Free;
   inherited;
   inherited;
 end;
 end;
 
 

BIN
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/QuickConfig.or


+ 24 - 6
samples/fpc/QuickConfig/ConfigToFileAndRegistry/lib/i386-win32/umain.lfm

@@ -1,28 +1,28 @@
 object Form1: TForm1
 object Form1: TForm1
   Left = 379
   Left = 379
-  Height = 433
+  Height = 457
   Top = 229
   Top = 229
   Width = 592
   Width = 592
   Caption = 'Form1'
   Caption = 'Form1'
-  ClientHeight = 433
+  ClientHeight = 457
   ClientWidth = 592
   ClientWidth = 592
   OnClose = FormClose
   OnClose = FormClose
   OnCreate = FormCreate
   OnCreate = FormCreate
   LCLVersion = '1.9.0.0'
   LCLVersion = '1.9.0.0'
   object btnSaveJson: TButton
   object btnSaveJson: TButton
-    Left = 456
+    Left = 448
     Height = 25
     Height = 25
     Top = 384
     Top = 384
-    Width = 107
+    Width = 120
     Caption = 'Save to Json'
     Caption = 'Save to Json'
     OnClick = btnSaveJsonClick
     OnClick = btnSaveJsonClick
     TabOrder = 0
     TabOrder = 0
   end
   end
   object btnLoadJson: TButton
   object btnLoadJson: TButton
-    Left = 336
+    Left = 312
     Height = 25
     Height = 25
     Top = 384
     Top = 384
-    Width = 107
+    Width = 123
     Caption = 'Load From Json'
     Caption = 'Load From Json'
     OnClick = btnLoadJsonClick
     OnClick = btnLoadJsonClick
     TabOrder = 1
     TabOrder = 1
@@ -36,4 +36,22 @@ object Form1: TForm1
     ScrollBars = ssAutoBoth
     ScrollBars = ssAutoBoth
     TabOrder = 2
     TabOrder = 2
   end
   end
+  object btnSaveRegistry: TButton
+    Left = 448
+    Height = 25
+    Top = 416
+    Width = 120
+    Caption = 'Save to Registry'
+    OnClick = btnSaveRegistryClick
+    TabOrder = 3
+  end
+  object btnLoadRegistry: TButton
+    Left = 312
+    Height = 25
+    Top = 416
+    Width = 123
+    Caption = 'Load From Registry'
+    OnClick = btnLoadRegistryClick
+    TabOrder = 4
+  end
 end
 end

+ 24 - 6
samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.lfm

@@ -1,28 +1,28 @@
 object Form1: TForm1
 object Form1: TForm1
   Left = 379
   Left = 379
-  Height = 433
+  Height = 457
   Top = 229
   Top = 229
   Width = 592
   Width = 592
   Caption = 'Form1'
   Caption = 'Form1'
-  ClientHeight = 433
+  ClientHeight = 457
   ClientWidth = 592
   ClientWidth = 592
   OnClose = FormClose
   OnClose = FormClose
   OnCreate = FormCreate
   OnCreate = FormCreate
   LCLVersion = '1.9.0.0'
   LCLVersion = '1.9.0.0'
   object btnSaveJson: TButton
   object btnSaveJson: TButton
-    Left = 456
+    Left = 448
     Height = 25
     Height = 25
     Top = 384
     Top = 384
-    Width = 107
+    Width = 120
     Caption = 'Save to Json'
     Caption = 'Save to Json'
     OnClick = btnSaveJsonClick
     OnClick = btnSaveJsonClick
     TabOrder = 0
     TabOrder = 0
   end
   end
   object btnLoadJson: TButton
   object btnLoadJson: TButton
-    Left = 336
+    Left = 312
     Height = 25
     Height = 25
     Top = 384
     Top = 384
-    Width = 107
+    Width = 123
     Caption = 'Load From Json'
     Caption = 'Load From Json'
     OnClick = btnLoadJsonClick
     OnClick = btnLoadJsonClick
     TabOrder = 1
     TabOrder = 1
@@ -36,4 +36,22 @@ object Form1: TForm1
     ScrollBars = ssAutoBoth
     ScrollBars = ssAutoBoth
     TabOrder = 2
     TabOrder = 2
   end
   end
+  object btnSaveRegistry: TButton
+    Left = 448
+    Height = 25
+    Top = 416
+    Width = 120
+    Caption = 'Save to Registry'
+    OnClick = btnSaveRegistryClick
+    TabOrder = 3
+  end
+  object btnLoadRegistry: TButton
+    Left = 312
+    Height = 25
+    Top = 416
+    Width = 123
+    Caption = 'Load From Registry'
+    OnClick = btnLoadRegistryClick
+    TabOrder = 4
+  end
 end
 end

+ 101 - 38
samples/fpc/QuickConfig/ConfigToFileAndRegistry/umain.pas

@@ -7,28 +7,44 @@ interface
 uses
 uses
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
   Quick.Config,
   Quick.Config,
-  //Quick.Config.Provider.Registry,
+  Quick.Config.Provider.Registry,
   Generics.Collections,
   Generics.Collections,
+  {$IFDEF FPC}
+  registry,
+  {$ENDIF}
   Quick.Config.Provider.Json;
   Quick.Config.Provider.Json;
 
 
 type
 type
 
 
   TMyPriority = (msLow, msMed, msHigh);
   TMyPriority = (msLow, msMed, msHigh);
 
 
-  TWinPos = record
-    PosX : Integer;
-    PosY : Integer;
+  TWinPos = class
+  private
+    fPosX : Integer;
+    fPosY : Integer;
+  published
+    property PosX : Integer read fPosX write fPosX;
+    property PosY : Integer read fPosY write fPosY;
   end;
   end;
 
 
-  TProcessType = record
-    Id : Integer;
-    Priority : TMyPriority;
-    Redundant : Boolean;
+  TProcessType = class
+  private
+    fId : Integer;
+    fPriority : TMyPriority;
+    fRedundant : Boolean;
+  published
+    property Id : Integer read fId write fId;
+    property Priority : TMyPriority read fPriority write fPriority;
+    property Redundant : Boolean read fRedundant write fRedundant;
   end;
   end;
 
 
   TWorker = class
   TWorker = class
-    Name : string;
-    Active : Boolean;
+  private
+    fName : string;
+    fActive : Boolean;
+  published
+    property Name : string read fName write fName;
+    property Active : Boolean read fActive write fActive;
   end;
   end;
 
 
   TMyConfig2 = class(TAppConfig)
   TMyConfig2 = class(TAppConfig)
@@ -43,29 +59,42 @@ type
     fTitle : string;
     fTitle : string;
     fHidden : Boolean;
     fHidden : Boolean;
     fSessionName: string;
     fSessionName: string;
+    fSizes : TArray<Integer>;
+    fLastFilename : string;
+    fWindowPos : TWinPos;
+    fHistory : TArray<TProcessType>;
+    fComplex : TProcessType;
+    fModifyDate : TDateTime;
+    fWorkList : TObjectList<TWorker>;
   public
   public
-    Sizes : array of Integer;
-    LastFilename : string;
-    WindowPos : TWinPos;
-    History : array of TProcessType;
-    Complex : TProcessType;
-    ModifyDate : TDateTime;
-    WorkList : TObjectList<TWorker>;
     constructor Create; override;
     constructor Create; override;
     destructor Destroy; override;
     destructor Destroy; override;
     procedure DefaultValues;
     procedure DefaultValues;
+    property Hidden : Boolean read fHidden write fHidden;
+  published
     property Title : string read fTitle write fTitle;
     property Title : string read fTitle write fTitle;
     property SessionName : string read fSessionName write fSessionName;
     property SessionName : string read fSessionName write fSessionName;
+    property Sizes : TArray<Integer> read fSizes write fSizes;
+    property LastFilename : string read fLastFilename write fLastFilename;
+    //property WindowPos : TWinPos read fWindowPos write fWindowPos;
+    property History : TArray<TProcessType> read fHistory write fHistory;
+    property Complex : TProcessType read fComplex write fComplex;
+    property ModifyDate : TDateTime read fModifyDate write fModifyDate;
+    //property WorkList : TObjectList<TWorker> read fWorkList write fWorkList;
   end;
   end;
 
 
   { TForm1 }
   { TForm1 }
 
 
   TForm1 = class(TForm)
   TForm1 = class(TForm)
+    btnLoadRegistry: TButton;
     btnSaveJson: TButton;
     btnSaveJson: TButton;
     btnLoadJson: TButton;
     btnLoadJson: TButton;
+    btnSaveRegistry: TButton;
     meInfo: TMemo;
     meInfo: TMemo;
     procedure btnLoadJsonClick(Sender: TObject);
     procedure btnLoadJsonClick(Sender: TObject);
+    procedure btnLoadRegistryClick(Sender: TObject);
     procedure btnSaveJsonClick(Sender: TObject);
     procedure btnSaveJsonClick(Sender: TObject);
+    procedure btnSaveRegistryClick(Sender: TObject);
     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
   private
   private
@@ -79,29 +108,50 @@ type
 var
 var
   Form1: TForm1;
   Form1: TForm1;
   ConfigJson : TMyConfig;
   ConfigJson : TMyConfig;
-  ConfigJson2 : TMyConfig2;
   ConfigReg : TMyConfig;
   ConfigReg : TMyConfig;
   ConfigTest : TMyConfig;
   ConfigTest : TMyConfig;
-  AppConfigJson : TAppConfigJsonProvider<TMyConfig2>;
-  //AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
+  AppConfigJson : TAppConfigJsonProvider<TMyConfig>;
+  AppConfigReg : TAppConfigRegistryProvider<TMyConfig>;
 
 
 implementation
 implementation
 
 
 {$R *.lfm}
 {$R *.lfm}
 
 
+uses
+  Quick.Json.Serializer;
+
 { TForm1 }
 { TForm1 }
 
 
 procedure TForm1.btnSaveJsonClick(Sender: TObject);
 procedure TForm1.btnSaveJsonClick(Sender: TObject);
 begin
 begin
   SetConfig(ConfigJson);
   SetConfig(ConfigJson);
-  AppConfigJson.Save(ConfigJson2);
+  AppConfigJson.Save(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJson);
   meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
   meInfo.Lines.Add('Saved Config in Json at ' + DateTimeToStr(ConfigJson.LastSaved));
 end;
 end;
 
 
+procedure TForm1.btnSaveRegistryClick(Sender: TObject);
+begin
+  SetConfig(ConfigJson);
+  AppConfigReg.Save(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJson);
+  meInfo.Lines.Add('Saved Config in Registry at ' + DateTimeToStr(ConfigJson.LastSaved));
+end;
+
 procedure TForm1.btnLoadJsonClick(Sender: TObject);
 procedure TForm1.btnLoadJsonClick(Sender: TObject);
 begin
 begin
   meInfo.Lines.Add('Load ConfigJson');
   meInfo.Lines.Add('Load ConfigJson');
-  AppConfigJson.Load(ConfigJson2);
+  ConfigJson := TMyConfig.Create;
+  AppConfigJson.Load(ConfigJson);
+  meInfo.Lines.Add(ConfigJson.ToJSON);
+  if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
+end;
+
+procedure TForm1.btnLoadRegistryClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigRegistry');
+  ConfigJson := TMyConfig.Create;
+  AppConfigReg.Load(ConfigJson);
   meInfo.Lines.Add(ConfigJson.ToJSON);
   meInfo.Lines.Add(ConfigJson.ToJSON);
   if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
   if TestConfig(ConfigTest,ConfigJson) then meInfo.Lines.Add('Test passed successfully!');
 end;
 end;
@@ -114,16 +164,16 @@ begin
     Assert(cConfig1.LastFilename = cConfig2.LastFilename);
     Assert(cConfig1.LastFilename = cConfig2.LastFilename);
     for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
     for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
       Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
       Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
-    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
-    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    //Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    //Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
     Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
     Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
     Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
     Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
     Assert(cConfig1.Title = cConfig2.Title);
     Assert(cConfig1.Title = cConfig2.Title);
-    for i := 0 to cConfig1.WorkList.Count - 1 do
-    begin
-      Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
-      Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
-    end;
+    //for i := 0 to cConfig1.WorkList.Count - 1 do
+    //begin
+    //  Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
+    //  Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
+    //end;
     for i := 0 to High(cConfig1.History) do
     for i := 0 to High(cConfig1.History) do
     begin
     begin
       Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
       Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
@@ -139,7 +189,7 @@ end;
 procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
 begin
 begin
   if Assigned(AppConfigJson) then AppConfigJson.Free;
   if Assigned(AppConfigJson) then AppConfigJson.Free;
-  //if Assigned(AppConfigReg) then AppConfigReg.Free;
+  if Assigned(AppConfigReg) then AppConfigReg.Free;
   if Assigned(ConfigTest) then ConfigTest.Free;
   if Assigned(ConfigTest) then ConfigTest.Free;
   if Assigned(ConfigReg) then ConfigReg.Free;
   if Assigned(ConfigReg) then ConfigReg.Free;
   if Assigned(ConfigJson) then ConfigJson.Free;
   if Assigned(ConfigJson) then ConfigJson.Free;
@@ -149,17 +199,30 @@ procedure TForm1.FormCreate(Sender: TObject);
 begin
 begin
   ConfigTest := TMyConfig.Create;
   ConfigTest := TMyConfig.Create;
   SetConfig(ConfigTest);
   SetConfig(ConfigTest);
-  AppConfigJson := TAppConfigJsonProvider<TMyConfig2>.Create(ConfigJson2);
+  AppConfigJson := TAppConfigJsonProvider<TMyConfig>.Create(ConfigJson);
   AppConfigJson.CreateIfNotExists := True;
   AppConfigJson.CreateIfNotExists := True;
-  AppConfigJson.Filename := 'Config.json';
-  //AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
-  //AppConfigReg.HRoot := HKEY_CURRENT_USER;
-  //AppConfigReg.MainKey := '_AppConfig';
+  AppConfigJson.Filename := '.\Config.json';
+  ConfigJson := TMyConfig.Create;
+  AppConfigReg := TAppConfigRegistryProvider<TMyConfig>.Create(ConfigReg);
+  AppConfigReg.HRoot := HKEY_CURRENT_USER;
+  AppConfigReg.MainKey := '_AppConfig';
 end;
 end;
 
 
 procedure TForm1.SetConfig(cConfig: TMyConfig);
 procedure TForm1.SetConfig(cConfig: TMyConfig);
+var
+  processtype : TProcessType;
 begin
 begin
-
+  cConfig.Title := 'hola';
+  cConfig.Complex := TProcessType.Create;
+  cConfig.Complex.Id := 1;
+  cConfig.Complex.Redundant := True;
+  cConfig.Complex.Priority := TMyPriority.msMed;
+  //processtype := TProcessType.Create;
+  //processtype.Id := 1;
+  //processtype.Priority := msLow;
+  //processtype.Redundant := True;
+  //cConfig.History := [processtype];
+  cConfig.ModifyDate := Now();
 end;
 end;
 
 
 { TMyConfig }
 { TMyConfig }
@@ -167,7 +230,7 @@ end;
 constructor TMyConfig.Create;
 constructor TMyConfig.Create;
 begin
 begin
   inherited;
   inherited;
-  WorkList := TObjectList<TWorker>.Create(True);
+  //WorkList := TObjectList<TWorker>.Create(True);
   DefaultValues;
   DefaultValues;
 end;
 end;
 
 
@@ -178,7 +241,7 @@ end;
 
 
 destructor TMyConfig.Destroy;
 destructor TMyConfig.Destroy;
 begin
 begin
-  if Assigned(WorkList) then WorkList.Free;
+  //if Assigned(WorkList) then WorkList.Free;
   inherited;
   inherited;
 end;
 end;
 
 

BIN
samples/fpc/QuickJsonSerializer/JsonSerializer.ico


+ 84 - 0
samples/fpc/QuickJsonSerializer/JsonSerializer.lpi

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="JsonSerializer"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </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="LCL"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="JsonSerializer.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="main.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="..\..\..\quick.json.fpc.utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="Quick.Json.fpc.Utils"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="JsonSerializer"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <Libraries Value="..\..\.."/>
+      <OtherUnitFiles Value="..\..\.."/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 22 - 0
samples/fpc/QuickJsonSerializer/JsonSerializer.lpr

@@ -0,0 +1,22 @@
+program JsonSerializer;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Interfaces, // this includes the LCL widgetset
+  Forms, main
+  { you can add units after this };
+
+{$R *.res}
+
+begin
+  RequireDerivedFormResource:=True;
+  Application.Scaled:=True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
+

BIN
samples/fpc/QuickJsonSerializer/JsonSerializer.res


BIN
samples/fpc/QuickJsonSerializer/lib/i386-win32/JsonSerializer.or


BIN
samples/fpc/QuickJsonSerializer/lib/i386-win32/JsonSerializer.res


+ 40 - 0
samples/fpc/QuickJsonSerializer/lib/i386-win32/main.lfm

@@ -0,0 +1,40 @@
+object Form1: TForm1
+  Left = 343
+  Height = 621
+  Top = 226
+  Width = 1025
+  Caption = 'Form1'
+  ClientHeight = 621
+  ClientWidth = 1025
+  OnClose = FormClose
+  OnCreate = FormCreate
+  LCLVersion = '1.9.0.0'
+  object Memo1: TMemo
+    Left = 8
+    Height = 540
+    Top = 8
+    Width = 1008
+    Lines.Strings = (
+      'Memo1'
+    )
+    TabOrder = 0
+  end
+  object btnFromJson: TButton
+    Left = 920
+    Height = 25
+    Top = 582
+    Width = 94
+    Caption = 'FromJson'
+    OnClick = btnFromJsonClick
+    TabOrder = 1
+  end
+  object btnToJson: TButton
+    Left = 808
+    Height = 25
+    Top = 582
+    Width = 99
+    Caption = 'ToJson'
+    OnClick = btnToJsonClick
+    TabOrder = 2
+  end
+end

+ 40 - 0
samples/fpc/QuickJsonSerializer/main.lfm

@@ -0,0 +1,40 @@
+object Form1: TForm1
+  Left = 343
+  Height = 621
+  Top = 226
+  Width = 1025
+  Caption = 'Form1'
+  ClientHeight = 621
+  ClientWidth = 1025
+  OnClose = FormClose
+  OnCreate = FormCreate
+  LCLVersion = '1.9.0.0'
+  object Memo1: TMemo
+    Left = 8
+    Height = 540
+    Top = 8
+    Width = 1008
+    Lines.Strings = (
+      'Memo1'
+    )
+    TabOrder = 0
+  end
+  object btnFromJson: TButton
+    Left = 920
+    Height = 25
+    Top = 582
+    Width = 94
+    Caption = 'FromJson'
+    OnClick = btnFromJsonClick
+    TabOrder = 1
+  end
+  object btnToJson: TButton
+    Left = 808
+    Height = 25
+    Top = 582
+    Width = 99
+    Caption = 'ToJson'
+    OnClick = btnToJsonClick
+    TabOrder = 2
+  end
+end

+ 239 - 0
samples/fpc/QuickJsonSerializer/main.pas

@@ -0,0 +1,239 @@
+unit main;
+
+{$mode delphi}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Quick.Json.Serializer,
+  Generics.Collections;
+
+type
+  TID = Int64;
+
+  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
+  private
+    fId : TID;
+    fName : string;
+    fSurname : string;
+    fAge : Integer;
+    fAddress : string;
+    fOptions : TOptions;
+    fLastConnections : TConnectionArray;
+    fMarried : Boolean;
+    fWorkingTime : TWorkingTime;
+    //[TCommentProperty('gnFemale or gnMale')]
+    fGenre : TGenre;
+    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;
+    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 }
+
+  TForm1 = class(TForm)
+    btnFromJson: TButton;
+    btnToJson: TButton;
+    Memo1: TMemo;
+    procedure btnFromJsonClick(Sender: TObject);
+    procedure btnToJsonClick(Sender: TObject);
+    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+    procedure FormCreate(Sender: TObject);
+  private
+
+  public
+
+  end;
+
+var
+  serializer : TJsonSerializer;
+  User : TUser;
+  UserList : TUserList;
+
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.btnToJsonClick(Sender: TObject);
+begin
+  Memo1.Text := serializer.ObjectToJson(User);
+  btnFromJson.Enabled := True;
+end;
+
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+  User.Free;
+  serializer.Free;
+end;
+
+procedure TForm1.btnFromJsonClick(Sender: TObject);
+var
+  newuser : TUser;
+begin
+  newuser := TUser.Create;
+  try
+    newuser := serializer.JsonToObject(newuser,Memo1.Text) as TUser;
+    Memo1.Lines.Add('NewUser:');
+    Memo1.Lines.Add(serializer.ObjectToJson(newuser));
+  finally
+    newuser.Free;
+  end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+var
+  lastcon : TConnectionInfo;
+  group : TGroup;
+begin
+  serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
+  user := TUser.Create;
+  user.Id := 77;
+  user.Name := 'Joe';
+  user.Surname := 'Smith';
+  user.Age := 30;
+  user.Married := True;
+  user.Address := 'Sunset st. 2';
+  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';
+  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.
+