Quick.Config.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. Rest.Json.Types,
  39. Rest.Json;
  40. {$ENDIF}
  41. {$ENDIF}
  42. type
  43. TDateTimeZone = (tzLocal, tzUTC);
  44. IAppConfigProvider<T> = interface
  45. ['{D55B1EBF-47F6-478B-8F70-9444575CB825}']
  46. procedure Load(var cConfig : T);
  47. procedure Save(var cConfig : T);
  48. end;
  49. TAppConfigProviderBase<T : class> = class(TInterfacedObject,IAppConfigProvider<T>)
  50. private
  51. fCreateIfNotExists : Boolean;
  52. public
  53. constructor Create(var cConfig : T); virtual;
  54. property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
  55. function InitObject : T;
  56. procedure Load(var cConfig : T); virtual; abstract;
  57. procedure Save(var cConfig : T); virtual; abstract;
  58. end;
  59. TApplyConfigEvent = procedure of object;
  60. {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
  61. TAppConfig = class{$IFDEF FPC}(TPersistent){$ENDIF}
  62. private
  63. {$IFDEF FPC}
  64. fOnApplyConfig : TApplyConfigEvent;
  65. fDateTimeZone: TDateTimeZone;
  66. fJsonIndent: Boolean;
  67. fLastSaved : TDateTime;
  68. {$ELSE}
  69. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  70. fOnApplyConfig : TApplyConfigEvent;
  71. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  72. fDateTimeZone: TDateTimeZone;
  73. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  74. fJsonIndent: Boolean;
  75. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  76. fLastSaved : TDateTime;
  77. {$ENDIF}
  78. public
  79. constructor Create; virtual;
  80. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  81. property OnApplyConfig : TApplyConfigEvent read fOnApplyConfig write fOnApplyConfig;
  82. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  83. property DateTimeZone : TDateTimeZone read fDateTimeZone write fDateTimeZone;
  84. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  85. property JsonIndent : Boolean read fJsonIndent write fJsonIndent;
  86. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  87. property LastSaved : TDateTime read fLastSaved write fLastSaved;
  88. procedure Apply;
  89. procedure DefaultValues; virtual;
  90. function ToJSON : string;
  91. procedure FromJSON(const json : string);
  92. end;
  93. {Usage: create a descend class from TAppConfig and add public properties to be loaded/saved
  94. TMyConfig = class(TAppConfig)
  95. private
  96. fName : string;
  97. fSurname : string;
  98. fStatus : Integer;
  99. public
  100. property Name : string read fName write fName;
  101. property SurName : string read fSurname write fSurname;
  102. property Status : Integer read fStatus write fStatus;
  103. end;
  104. AppConfigProvider := TAppConfigJsonProvider<TMyConfig>.Create(MyConfig);
  105. MyConfig.Name := 'John';
  106. }
  107. implementation
  108. { TAppConfigProviderBase }
  109. constructor TAppConfigProviderBase<T>.Create(var cConfig : T);
  110. begin
  111. fCreateIfNotExists := True;
  112. //create object with rtti
  113. if Assigned(cConfig) then cConfig.Free;
  114. cConfig := InitObject;
  115. end;
  116. function TAppConfigProviderBase<T>.InitObject : T;
  117. var
  118. AValue: TValue;
  119. ctx: TRttiContext;
  120. rType: TRttiType;
  121. AMethCreate: TRttiMethod;
  122. begin
  123. ctx := TRttiContext.Create;
  124. try
  125. rType := ctx.GetType(TypeInfo(T));
  126. for AMethCreate in rType.GetMethods do
  127. begin
  128. if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then
  129. begin
  130. {$IFDEF FPC}
  131. Result := T(GetClass(T.ClassName).Create);
  132. {$ELSE}
  133. AValue := AMethCreate.Invoke(rType.AsInstance.AsInstance.MetaclassType,[]);
  134. Result := AValue.AsType<T>;
  135. {$ENDIF}
  136. Break;
  137. end;
  138. end;
  139. finally
  140. ctx.Free;
  141. end;
  142. end;
  143. { TAppConfig }
  144. constructor TAppConfig.Create;
  145. begin
  146. fDateTimeZone := TDateTimeZone.tzLocal;
  147. fJsonIndent := True;
  148. fLastSaved := 0;
  149. end;
  150. procedure TAppConfig.Apply;
  151. begin
  152. if Assigned(fOnApplyConfig) then fOnApplyConfig;
  153. end;
  154. procedure TAppConfig.DefaultValues;
  155. begin
  156. //inherit to set default values if no config exists before
  157. end;
  158. function TAppConfig.ToJSON : string;
  159. {$IFDEF DELPHIRX102_UP}
  160. var
  161. Serializer : TJsonSerializer;
  162. {$ENDIF}
  163. {$IFDEF FPC}
  164. var
  165. streamer : TJsonStreamer;
  166. {$ENDIF}
  167. begin
  168. Result := '';
  169. try
  170. {$IFDEF DELPHIRX102_UP}
  171. Serializer := TJsonSerializer.Create;
  172. try
  173. Serializer.Formatting := TJsonFormatting.Indented;
  174. if JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
  175. if DateTimeZone = TDateTimeZone.tzLocal then
  176. begin
  177. Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Local;
  178. Serializer.DateFormatHandling := TJsonDateFormatHandling.FormatSettings;
  179. end
  180. else Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Utc;
  181. Result := Serializer.Serialize<TObject>(Self);
  182. finally
  183. Serializer.Free;
  184. end;
  185. {$ELSE}
  186. {$IFDEF FPC}
  187. streamer := TJsonStreamer.Create(nil);
  188. try
  189. Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
  190. Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
  191. Result := streamer.ObjectToJSON(Self).ToString;
  192. finally
  193. streamer.Free;
  194. end;
  195. {$ELSE}
  196. Result := TJson.ObjectToJsonString(Self);
  197. {$ENDIF}
  198. {$ENDIF}
  199. except
  200. on e : Exception do raise Exception.Create(e.Message);
  201. end;
  202. end;
  203. procedure TAppConfig.FromJSON(const json : string);
  204. {$IFDEF DELPHIRX102_UP}
  205. var
  206. Serializer : TJsonSerializer;
  207. {$ENDIF}
  208. {$IFDEF FPC}
  209. var
  210. streamer : TJSONDeStreamer;
  211. {$ENDIF}
  212. begin
  213. try
  214. {$IFDEF DELPHIRX102_UP}
  215. Serializer := TJsonSerializer.Create;
  216. try
  217. Serializer.Formatting := TJsonFormatting.Indented;
  218. if JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
  219. if DateTimeZone = TDateTimeZone.tzLocal then
  220. begin
  221. Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Local;
  222. Serializer.DateFormatHandling := TJsonDateFormatHandling.FormatSettings;
  223. end
  224. else Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Utc;
  225. Self := Serializer.Deserialize<TAppConfig>(json);
  226. finally
  227. Serializer.Free;
  228. end;
  229. {$ELSE}
  230. {$IFDEF FPC}
  231. streamer := TJSONDeStreamer.Create(nil);
  232. try
  233. //Streamer.Options := Streamer. .Options + [jsoDateTimeAsString ,jsoUseFormatString];
  234. Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
  235. Streamer.JsonToObject(json,Self);
  236. finally
  237. Streamer.Free;
  238. end;
  239. {$ELSE}
  240. TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json)));
  241. {$ENDIF}
  242. {$ENDIF}
  243. except
  244. on e : Exception do raise Exception.Create(e.Message);
  245. end;
  246. end;
  247. end.