Quick.Config.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. { ***************************************************************************
  2. Copyright (c) 2015-2018 Kike Pérez
  3. Unit : Quick.Config
  4. Description : Load/Save config from/to JSON file
  5. Author : Kike Pérez
  6. Version : 1.4
  7. Created : 26/01/2017
  8. Modified : 07/04/2018
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Config;
  22. interface
  23. {$i QuickLib.inc}
  24. uses
  25. Classes,
  26. SysUtils,
  27. Rtti,
  28. {$IFDEF DELPHIRX102_UP}
  29. DBXJSON,
  30. JSON.Types,
  31. JSON.Serializers;
  32. {$ELSE}
  33. {$IFDEF FPC}
  34. fpjson,
  35. fpjsonrtti;
  36. {$ELSE}
  37. DBXJSON,
  38. System.JSON,
  39. Rest.Json.Types,
  40. Rest.Json;
  41. {$ENDIF}
  42. {$ENDIF}
  43. type
  44. TDateTimeZone = (tzLocal, tzUTC);
  45. IAppConfigProvider<T> = interface
  46. ['{D55B1EBF-47F6-478B-8F70-9444575CB825}']
  47. procedure Load(var cConfig : T);
  48. procedure Save(var cConfig : T);
  49. end;
  50. TAppConfigProviderBase<T : class> = class(TInterfacedObject,IAppConfigProvider<T>)
  51. private
  52. fCreateIfNotExists : Boolean;
  53. public
  54. constructor Create(var cConfig : T); virtual;
  55. property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
  56. function InitObject : T;
  57. procedure Load(var cConfig : T); virtual; abstract;
  58. procedure Save(var cConfig : T); virtual; abstract;
  59. end;
  60. TApplyConfigEvent = procedure of object;
  61. {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
  62. TAppConfig = class{$IFDEF FPC}(TPersistent){$ENDIF}
  63. private
  64. {$IFDEF FPC}
  65. fOnApplyConfig : TApplyConfigEvent;
  66. fDateTimeZone: TDateTimeZone;
  67. fJsonIndent: Boolean;
  68. fLastSaved : TDateTime;
  69. {$ELSE}
  70. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  71. fOnApplyConfig : TApplyConfigEvent;
  72. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  73. fDateTimeZone: TDateTimeZone;
  74. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  75. fJsonIndent: Boolean;
  76. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  77. fLastSaved : TDateTime;
  78. {$ENDIF}
  79. public
  80. constructor Create; virtual;
  81. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  82. property OnApplyConfig : TApplyConfigEvent read fOnApplyConfig write fOnApplyConfig;
  83. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  84. property DateTimeZone : TDateTimeZone read fDateTimeZone write fDateTimeZone;
  85. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  86. property JsonIndent : Boolean read fJsonIndent write fJsonIndent;
  87. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  88. property LastSaved : TDateTime read fLastSaved write fLastSaved;
  89. procedure Apply;
  90. procedure DefaultValues; virtual;
  91. function ToJSON : string;
  92. procedure FromJSON(const json : string);
  93. end;
  94. {Usage: create a descend class from TAppConfig and add public properties to be loaded/saved
  95. TMyConfig = class(TAppConfig)
  96. private
  97. fName : string;
  98. fSurname : string;
  99. fStatus : Integer;
  100. public
  101. property Name : string read fName write fName;
  102. property SurName : string read fSurname write fSurname;
  103. property Status : Integer read fStatus write fStatus;
  104. end;
  105. AppConfigProvider := TAppConfigJsonProvider<TMyConfig>.Create(MyConfig);
  106. MyConfig.Name := 'John';
  107. }
  108. implementation
  109. { TAppConfigProviderBase }
  110. constructor TAppConfigProviderBase<T>.Create(var cConfig : T);
  111. begin
  112. fCreateIfNotExists := True;
  113. //create object with rtti
  114. if Assigned(cConfig) then cConfig.Free;
  115. cConfig := InitObject;
  116. end;
  117. function TAppConfigProviderBase<T>.InitObject : T;
  118. var
  119. AValue: TValue;
  120. ctx: TRttiContext;
  121. rType: TRttiType;
  122. AMethCreate: TRttiMethod;
  123. begin
  124. ctx := TRttiContext.Create;
  125. try
  126. rType := ctx.GetType(TypeInfo(T));
  127. for AMethCreate in rType.GetMethods do
  128. begin
  129. if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then
  130. begin
  131. {$IFDEF FPC}
  132. Result := T(GetClass(T.ClassName).Create);
  133. {$ELSE}
  134. AValue := AMethCreate.Invoke(rType.AsInstance.AsInstance.MetaclassType,[]);
  135. Result := AValue.AsType<T>;
  136. {$ENDIF}
  137. Break;
  138. end;
  139. end;
  140. finally
  141. ctx.Free;
  142. end;
  143. end;
  144. { TAppConfig }
  145. constructor TAppConfig.Create;
  146. begin
  147. fDateTimeZone := TDateTimeZone.tzLocal;
  148. fJsonIndent := True;
  149. fLastSaved := 0;
  150. end;
  151. procedure TAppConfig.Apply;
  152. begin
  153. if Assigned(fOnApplyConfig) then fOnApplyConfig;
  154. end;
  155. procedure TAppConfig.DefaultValues;
  156. begin
  157. //inherit to set default values if no config exists before
  158. end;
  159. function TAppConfig.ToJSON : string;
  160. {$IFDEF DELPHIRX102_UP}
  161. var
  162. Serializer : TJsonSerializer;
  163. {$ENDIF}
  164. {$IFDEF FPC}
  165. var
  166. streamer : TJsonStreamer;
  167. {$ENDIF}
  168. begin
  169. Result := '';
  170. try
  171. {$IFDEF DELPHIRX102_UP}
  172. Serializer := TJsonSerializer.Create;
  173. try
  174. Serializer.Formatting := TJsonFormatting.Indented;
  175. if JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
  176. if DateTimeZone = TDateTimeZone.tzLocal then
  177. begin
  178. Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Local;
  179. Serializer.DateFormatHandling := TJsonDateFormatHandling.FormatSettings;
  180. end
  181. else Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Utc;
  182. Result := Serializer.Serialize<TObject>(Self);
  183. finally
  184. Serializer.Free;
  185. end;
  186. {$ELSE}
  187. {$IFDEF FPC}
  188. streamer := TJsonStreamer.Create(nil);
  189. try
  190. Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
  191. Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
  192. Result := streamer.ObjectToJSON(Self).ToString;
  193. finally
  194. streamer.Free;
  195. end;
  196. {$ELSE}
  197. Result := TJson.ObjectToJsonString(Self);
  198. {$ENDIF}
  199. {$ENDIF}
  200. except
  201. on e : Exception do raise Exception.Create(e.Message);
  202. end;
  203. end;
  204. procedure TAppConfig.FromJSON(const json : string);
  205. {$IFDEF DELPHIRX102_UP}
  206. var
  207. Serializer : TJsonSerializer;
  208. {$ENDIF}
  209. {$IFDEF FPC}
  210. var
  211. streamer : TJSONDeStreamer;
  212. {$ENDIF}
  213. begin
  214. try
  215. {$IFDEF DELPHIRX102_UP}
  216. Serializer := TJsonSerializer.Create;
  217. try
  218. Serializer.Formatting := TJsonFormatting.Indented;
  219. if JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
  220. if DateTimeZone = TDateTimeZone.tzLocal then
  221. begin
  222. Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Local;
  223. Serializer.DateFormatHandling := TJsonDateFormatHandling.FormatSettings;
  224. end
  225. else Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Utc;
  226. Self := Serializer.Deserialize<TAppConfig>(json);
  227. finally
  228. Serializer.Free;
  229. end;
  230. {$ELSE}
  231. {$IFDEF FPC}
  232. streamer := TJSONDeStreamer.Create(nil);
  233. try
  234. //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
  235. Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
  236. Streamer.JsonToObject(json,Self);
  237. finally
  238. Streamer.Free;
  239. end;
  240. {$ELSE}
  241. TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json)));
  242. {$ENDIF}
  243. {$ENDIF}
  244. except
  245. on e : Exception do raise Exception.Create(e.Message);
  246. end;
  247. end;
  248. end.