Quick.Json.Serializer.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. { ***************************************************************************
  2. Copyright (c) 2015-2018 Kike Pérez
  3. Unit : Quick.JSON.Serializer
  4. Description : Json Serializer
  5. Author : Kike Pérez
  6. Version : 1.4
  7. Created : 21/05/2018
  8. Modified : 16/10/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.Json.Serializer;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. Rtti,
  28. TypInfo,
  29. {$IFDEF FPC}
  30. rttiutils,
  31. fpjson,
  32. jsonparser,
  33. strUtils,
  34. //jsonreader,
  35. //fpjsonrtti,
  36. Quick.Json.fpc.Compatibility,
  37. {$ELSE}
  38. {$IFDEF DELPHIXE7_UP}
  39. System.Json,
  40. {$ENDIF}
  41. {$ENDIF}
  42. DateUtils,
  43. Quick.Commons,
  44. Quick.JSON.Utils;
  45. type
  46. EJsonSerializeError = class(Exception);
  47. EJsonDeserializeError = class(Exception);
  48. {$IFNDEF FPC}
  49. TNotSerializableProperty = class(TCustomAttribute);
  50. TCommentProperty = class(TCustomAttribute)
  51. private
  52. fComment : string;
  53. public
  54. constructor Create(const aComment: string);
  55. property Comment : string read fComment;
  56. end;
  57. TCustomNameProperty = class(TCustomAttribute)
  58. private
  59. fName : string;
  60. public
  61. constructor Create(const aName: string);
  62. property Name : string read fName;
  63. end;
  64. {$ENDIF}
  65. IJsonSerializer = interface
  66. ['{CA26F7AE-F1FE-41BE-9C23-723A687F60D1}']
  67. function JsonToObject(aType: TClass; const aJson: string): TObject; overload;
  68. function JsonToObject(aObject: TObject; const aJson: string): TObject; overload;
  69. function ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  70. end;
  71. TSerializeLevel = (slPublicProperty, slPublishedProperty);
  72. PValue = ^TValue;
  73. TRTTIJson = class
  74. private
  75. fSerializeLevel : TSerializeLevel;
  76. function GetValue(aAddr: Pointer; aType: TRTTIType): TValue; overload;
  77. function GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue; overload;
  78. function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
  79. function IsGenericList(aObject : TObject) : Boolean;
  80. function GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
  81. procedure SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue); overload;
  82. procedure SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue); overload;
  83. {$IFDEF FPC}
  84. function FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  85. function GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  86. procedure LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  87. {$ENDIF}
  88. public
  89. constructor Create(aSerializeLevel : TSerializeLevel);
  90. {$IFNDEF FPC}
  91. function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
  92. function DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
  93. {$ELSE}
  94. procedure DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
  95. {$ENDIF}
  96. function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
  97. function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
  98. {$IFNDEF FPC}
  99. function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
  100. {$ENDIF}
  101. function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
  102. {$IFNDEF FPC}
  103. function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
  104. {$ELSE}
  105. function DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
  106. {$ENDIF}
  107. {$IFNDEF FPC}
  108. function Serialize(const aName : string; aValue : TValue) : TJSONPair; overload;
  109. {$ELSE}
  110. function Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  111. function Serialize(const aName : string; aValue : TValue) : TJSONPair;
  112. {$ENDIF}
  113. function Serialize(aObject : TObject) : TJSONObject; overload;
  114. end;
  115. TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
  116. strict private
  117. fSerializeLevel : TSerializeLevel;
  118. fRTTIJson : TRTTIJson;
  119. public
  120. constructor Create(aSerializeLevel : TSerializeLevel);
  121. destructor Destroy; override;
  122. property SerializeLevel : TSerializeLevel read fSerializeLevel;
  123. function JsonToObject(aType : TClass; const aJson: string) : TObject; overload;
  124. function JsonToObject(aObject : TObject; const aJson: string) : TObject; overload;
  125. function ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  126. end;
  127. PPByte = ^PByte;
  128. resourcestring
  129. cNotSupportedDataType = 'Not supported "%s" data type "%s"';
  130. cNotSerializable = 'Object is not serializable';
  131. implementation
  132. { TRTTIJson }
  133. {$IFNDEF FPC}
  134. function TRTTIJson.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
  135. var
  136. rType: PTypeInfo;
  137. len: NativeInt;
  138. pArr: Pointer;
  139. rItemValue: TValue;
  140. i: Integer;
  141. objClass: TClass;
  142. ctx : TRttiContext;
  143. json : TJSONObject;
  144. rDynArray : TRttiDynamicArrayType;
  145. propObj : TObject;
  146. begin
  147. if GetTypeData(aTypeInfo).DynArrElType = nil then Exit;
  148. if not assigned(aJsonArray) then Exit;
  149. len := aJsonArray.Count;
  150. rType := GetTypeData(aTypeInfo).DynArrElType^;
  151. pArr := nil;
  152. DynArraySetLength(pArr,aTypeInfo, 1, @len);
  153. try
  154. TValue.Make(@pArr,aTypeInfo, Result);
  155. rDynArray := ctx.GetType(Result.TypeInfo) as TRTTIDynamicArrayType;
  156. for i := 0 to aJsonArray.Count - 1 do
  157. begin
  158. rItemValue := nil;
  159. case rType.Kind of
  160. tkClass :
  161. begin
  162. if aJsonArray.Items[i] is TJSONObject then
  163. begin
  164. propObj := GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i, rDynArray.ElementType).AsObject;
  165. if propObj = nil then
  166. begin
  167. objClass := rType.TypeData.ClassType;
  168. rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
  169. end
  170. else
  171. begin
  172. DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
  173. end;
  174. end;
  175. end;
  176. tkRecord :
  177. begin
  178. json := TJSONObject(aJsonArray.Items[i]);
  179. rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
  180. rDynArray.ElementType),aObject,json);
  181. end;
  182. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  183. begin
  184. //skip these properties
  185. end
  186. else
  187. begin
  188. rItemValue := DeserializeType(aObject,rType.Kind,aTypeInfo,aJsonArray.Items[i].Value);
  189. end;
  190. end;
  191. if not rItemValue.IsEmpty then Result.SetArrayElement(i,rItemValue);
  192. end;
  193. //aProperty.SetValue(aObject,rValue);
  194. finally
  195. DynArrayClear(pArr,aTypeInfo);
  196. end;
  197. end;
  198. {$ELSE}
  199. procedure TRTTIJson.DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
  200. var
  201. rType: PTypeInfo;
  202. len: NativeInt;
  203. pArr: Pointer;
  204. rItemValue: TValue;
  205. i: Integer;
  206. objClass: TClass;
  207. propObj : TObject;
  208. rValue : TValue;
  209. begin
  210. if GetTypeData(aTypeInfo).ElType2 = nil then Exit;
  211. len := aJsonArray.Count;
  212. rType := GetTypeData(aTypeInfo).ElType2;
  213. pArr := nil;
  214. DynArraySetLength(pArr,aTypeInfo, 1, @len);
  215. try
  216. TValue.Make(@pArr,aTypeInfo, rValue);
  217. for i := 0 to aJsonArray.Count - 1 do
  218. begin
  219. rItemValue := nil;
  220. case rType.Kind of
  221. tkClass :
  222. begin
  223. if aJsonArray.Items[i] is TJSONObject then
  224. begin
  225. propObj := GetValue(PPByte(rValue.GetReferenceToRawData)^ +GetTypeData(aTypeInfo).elSize * i, GetTypeData(aTypeInfo).ElType2).AsObject;
  226. if propObj = nil then
  227. begin
  228. objClass := GetTypeData(aTypeInfo).ClassType;
  229. rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
  230. end
  231. else
  232. begin
  233. DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
  234. end;
  235. end;
  236. end;
  237. tkRecord :
  238. begin
  239. {json := TJSONObject(aJsonArray.Items[i]);
  240. rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
  241. rDynArray.ElementType),aObject,json); }
  242. end;
  243. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  244. begin
  245. //skip these properties
  246. end
  247. else
  248. begin
  249. rItemValue := DeserializeType(aObject,GetTypeData(aTypeInfo).ElType2.Kind,aPropertyName,aJsonArray.Items[i].Value);
  250. end;
  251. end;
  252. if not rItemValue.IsEmpty then rValue.SetArrayElement(i,rItemValue);
  253. end;
  254. //aProperty.SetValue(aObject,rValue);
  255. SetDynArrayProp(aObject,GetPropInfo(aObject,aPropertyName),pArr);
  256. finally
  257. DynArrayClear(pArr,aTypeInfo);
  258. end;
  259. end;
  260. {$ENDIF}
  261. {$IFNDEF FPC}
  262. function TRTTIJson.DeserializeRecord(aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
  263. var
  264. ctx : TRttiContext;
  265. rRec : TRttiRecordType;
  266. rField : TRttiField;
  267. rValue : TValue;
  268. member : TJSONPair;
  269. jArray : TJSONArray;
  270. json : TJSONObject;
  271. objClass : TClass;
  272. propobj : TObject;
  273. begin
  274. rRec := ctx.GetType(aRecord.TypeInfo).AsRecord;
  275. try
  276. for rField in rRec.GetFields do
  277. begin
  278. rValue := nil;
  279. member := TJSONPair(aJson.GetValue(rField.Name));
  280. if member <> nil then
  281. case rField.FieldType.TypeKind of
  282. tkDynArray :
  283. begin
  284. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  285. try
  286. rValue := DeserializeDynArray(rField.FieldType.Handle,aObject,jArray);
  287. finally
  288. jArray.Free;
  289. end;
  290. end;
  291. tkClass :
  292. begin
  293. //if (member.JsonValue is TJSONObject) then
  294. begin
  295. propobj := rField.GetValue(@aRecord).AsObject;
  296. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  297. try
  298. if propobj = nil then
  299. begin
  300. objClass := rField.FieldType.Handle^.TypeData.ClassType;// aProperty.PropertyType.Handle^.TypeData.ClassType;
  301. rValue := DeserializeClass(objClass,json);
  302. end
  303. else
  304. begin
  305. DeserializeObject(propobj,json);
  306. end;
  307. finally
  308. json.Free;
  309. end;
  310. end
  311. end;
  312. else
  313. begin
  314. rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.toJson);
  315. end;
  316. end;
  317. if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
  318. end;
  319. Result := aRecord;
  320. finally
  321. ctx.Free;
  322. end;
  323. end;
  324. {$ENDIF}
  325. constructor TRTTIJson.Create(aSerializeLevel: TSerializeLevel);
  326. begin
  327. fSerializeLevel := aSerializeLevel;
  328. end;
  329. function TRTTIJson.DeserializeClass(aType: TClass; const aJson: TJSONObject): TObject;
  330. begin
  331. Result := nil;
  332. if (aJson = nil) or (aJson.Count = 0) then Exit;
  333. Result := aType.Create;
  334. try
  335. Result := DeserializeObject(Result,aJson);
  336. except
  337. on E : Exception do
  338. begin
  339. Result.Free;
  340. raise EJsonDeserializeError.CreateFmt('Deserialize error class "%s" : %s',[aType.ClassName,e.Message]);
  341. end;
  342. end;
  343. end;
  344. function TRTTIJson.DeserializeObject(aObject: TObject; const aJson: TJSONObject): TObject;
  345. var
  346. ctx: TRttiContext;
  347. rType: TRttiType;
  348. rProp: TRttiProperty;
  349. {$IFNDEF FPC}
  350. attr: TCustomAttribute;
  351. {$ENDIF}
  352. propertyname : string;
  353. begin
  354. Result := aObject;
  355. if (aJson = nil) or (aJson.Count = 0) or (Result = nil) then Exit;
  356. //if IsGenericList(aObject) then
  357. //begin
  358. // Result := DeserializeList(Result,aObject.ClassName,aJson);
  359. // Exit;
  360. //end;
  361. try
  362. rType := ctx.GetType(aObject.ClassInfo);
  363. try
  364. for rProp in rType.GetProperties do
  365. begin
  366. {$IFNDEF FPC}
  367. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  368. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  369. {$ENDIF}
  370. begin
  371. if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
  372. begin
  373. propertyname := rProp.Name;
  374. {$IFNDEF FPC}
  375. for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  376. if rProp.Name = 'List' then
  377. begin
  378. Result := DeserializeList(Result,propertyname,aJson);
  379. end
  380. else
  381. {$ENDIF}
  382. Result := DeserializeProperty(Result,propertyname,rProp,aJson);
  383. end;
  384. end;
  385. end;
  386. finally
  387. ctx.Free;
  388. end;
  389. except
  390. on E : Exception do
  391. begin
  392. Result.Free;
  393. raise EJsonDeserializeError.CreateFmt('Deserialize error for object "%s" : %s',[aObject.ClassName,e.Message]);
  394. end;
  395. end;
  396. end;
  397. {$IFNDEF FPC}
  398. function TRTTIJson.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
  399. var
  400. ctx : TRttiContext;
  401. rType : TRttiType;
  402. rfield : TRttiField;
  403. jarray : TJSONArray;
  404. member : TJSONPair;
  405. rvalue : TValue;
  406. i : Integer;
  407. rProp : TRttiProperty;
  408. begin
  409. Result := aObject;
  410. member := TJSONPair(aJson.GetValue(aName));
  411. rType := ctx.GetType(aObject.ClassInfo);
  412. try
  413. rProp := rType.GetProperty('List');
  414. if rProp = nil then Exit;
  415. finally
  416. ctx.Free;
  417. end;
  418. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  419. try
  420. rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
  421. i := jarray.Count;
  422. finally
  423. jArray.Free;
  424. end;
  425. if not rValue.IsEmpty then
  426. begin
  427. for rfield in rType.GetFields do
  428. begin
  429. if rfield.Name = 'FOwnsObjects' then rfield.SetValue(aObject,True);
  430. //if rfield.Name = 'FCount' then rfield.SetValue(aObject,i);
  431. if rfield.Name = 'FItems' then
  432. begin
  433. //if TList(aObject) <> nil then TList(aObject).Clear;
  434. //rfield.GetValue(aObject).AsObject.Free;// aValue.GetReferenceToRawData)
  435. rfield.SetValue(aObject,rValue);// .SetDynArrayProp(aObject,'fItems',Result);
  436. Break;
  437. end;
  438. end;
  439. rProp := rType.GetProperty('Count');
  440. rProp.SetValue(aObject,i);
  441. end;
  442. end;
  443. {$ENDIF}
  444. function TRTTIJson.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
  445. var
  446. rValue : TValue;
  447. {$IFNDEF FPC}
  448. member : TJSONPair;
  449. {$ELSE}
  450. member : TJsonObject;
  451. {$ENDIF}
  452. objClass: TClass;
  453. jArray : TJSONArray;
  454. json : TJSONObject;
  455. begin
  456. Result := aObject;
  457. rValue := nil;
  458. {$IFNDEF FPC}
  459. member := TJSONPair(aJson.GetValue(aName));
  460. {$ELSE}
  461. member := TJsonObject(aJson.Find(aName));
  462. {$ENDIF}
  463. if member <> nil then
  464. begin
  465. case aProperty.PropertyType.TypeKind of
  466. tkDynArray :
  467. begin
  468. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  469. try
  470. {$IFNDEF FPC}
  471. aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
  472. {$ELSE}
  473. DeserializeDynArray(aProperty.PropertyType.Handle,aName,Result,jArray);
  474. {$ENDIF}
  475. Exit;
  476. finally
  477. jArray.Free;
  478. end;
  479. end;
  480. tkClass :
  481. begin
  482. //if (member.JsonValue is TJSONObject) then
  483. begin
  484. json := TJsonObject(TJSONObject.ParseJSONValue(member.ToJson));
  485. try
  486. if aProperty.GetValue(aObject).AsObject = nil then
  487. begin
  488. {$IFNDEF FPC}
  489. objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
  490. rValue := DeserializeClass(objClass,json);
  491. {$ELSE}
  492. objClass := GetObjectPropClass(aObject,aName);
  493. //objClass := GetTypeData(aProperty.PropertyType.Handle)^.ClassType;
  494. rValue := DeserializeClass(objClass,json);
  495. SetObjectProp(aObject,aName,rValue.AsObject);
  496. Exit;
  497. {$ENDIF}
  498. end
  499. else
  500. begin
  501. rValue := DeserializeObject(aProperty.GetValue(aObject).AsObject,json);
  502. Exit;
  503. end;
  504. finally
  505. json.Free;
  506. end;
  507. end
  508. end;
  509. {$IFNDEF FPC}
  510. tkRecord :
  511. begin
  512. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  513. try
  514. rValue := DeserializeRecord(aProperty.GetValue(aObject),aObject,json);
  515. finally
  516. json.Free;
  517. end;
  518. end;
  519. {$ENDIF}
  520. else
  521. begin
  522. {$IFNDEF FPC}
  523. //avoid return unicode escaped chars if string
  524. if aProperty.PropertyType.TypeKind in [tkString, tkLString, tkWString, tkUString] then rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.JsonString.ToString)
  525. else rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
  526. {$ELSE}
  527. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
  528. if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
  529. {$ENDIF}
  530. end;
  531. end;
  532. {$IFNDEF FPC}
  533. if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
  534. {$ENDIF}
  535. end;
  536. end;
  537. {$IFNDEF FPC}
  538. function TRTTIJson.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
  539. var
  540. i : Integer;
  541. value : string;
  542. fsettings : TFormatSettings;
  543. begin
  544. try
  545. value := AnsiDequotedStr(aValue,'"');
  546. case aType of
  547. tkString, tkLString, tkWString, tkUString :
  548. begin
  549. Result := value;
  550. end;
  551. tkChar, tkWChar :
  552. begin
  553. Result := value;
  554. end;
  555. tkInteger :
  556. begin
  557. Result := StrToInt(value);
  558. end;
  559. tkInt64 :
  560. begin
  561. Result := StrToInt64(value);
  562. end;
  563. tkFloat :
  564. begin
  565. if aTypeInfo = TypeInfo(TDateTime) then
  566. begin
  567. Result := JsonDateToDateTime(value);
  568. end
  569. else if aTypeInfo = TypeInfo(TDate) then
  570. begin
  571. Result := StrToDate(value);
  572. end
  573. else if aTypeInfo = TypeInfo(TTime) then
  574. begin
  575. Result := StrToTime(value);
  576. end
  577. else
  578. begin
  579. fsettings := TFormatSettings.Create;
  580. Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
  581. end;
  582. end;
  583. tkEnumeration :
  584. begin
  585. if aTypeInfo = System.TypeInfo(Boolean) then
  586. begin
  587. Result := StrToBool(value);
  588. end
  589. else
  590. begin
  591. TValue.Make(GetEnumValue(aTypeInfo,value),aTypeInfo, Result);
  592. end;
  593. end;
  594. tkSet :
  595. begin
  596. i := StringToSet(aTypeInfo,value);
  597. TValue.Make(@i,aTypeInfo,Result);
  598. end;
  599. else
  600. begin
  601. //raise EclJsonSerializerError.Create('Not supported data type!');
  602. end;
  603. end;
  604. except
  605. on E : Exception do
  606. begin
  607. raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s.%s" : %s',[aObject.ClassName,GetTypeName(aTypeInfo),e.Message]);
  608. end;
  609. end;
  610. end;
  611. {$ELSE}
  612. function TRTTIJson.DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
  613. var
  614. value : string;
  615. propinfo : PPropInfo;
  616. fsettings : TFormatSettings;
  617. begin
  618. try
  619. value := AnsiDequotedStr(aValue,'"');
  620. if value = '' then
  621. begin
  622. Result := nil;
  623. Exit;
  624. end;
  625. propinfo := GetPropInfo(aObject,aPropertyName);
  626. //case propinfo.PropType.Kind of
  627. case aType of
  628. tkString, tkLString, tkWString, tkUString, tkAString :
  629. begin
  630. Result := value;
  631. //SetStrProp(aObject,propinfo,value);
  632. end;
  633. tkChar, tkWChar :
  634. begin
  635. Result := value;
  636. end;
  637. tkInteger :
  638. begin
  639. Result := StrToInt(value);
  640. end;
  641. tkInt64 :
  642. begin
  643. Result := StrToInt64(value);
  644. end;
  645. tkFloat :
  646. begin
  647. if propinfo.PropType = TypeInfo(TDateTime) then
  648. begin
  649. Result := JsonDateToDateTime(value);
  650. end
  651. else if propinfo.PropType = TypeInfo(TDate) then
  652. begin
  653. Result := StrToDate(value);
  654. end
  655. else if propinfo.PropType = TypeInfo(TTime) then
  656. begin
  657. Result := StrToTime(value);
  658. end
  659. else
  660. begin
  661. fsettings := DefaultFormatSettings;
  662. Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
  663. end;
  664. end;
  665. tkEnumeration:
  666. begin
  667. Result := value;
  668. end;
  669. tkBool :
  670. begin
  671. Result := StrToBool(value);
  672. end;
  673. tkSet :
  674. begin
  675. Result := value;
  676. end;
  677. else
  678. begin
  679. //raise EclJsonSerializerError.Create('Not supported data type!');
  680. end;
  681. end;
  682. //if not Result.IsEmpty then SetPropertyValue(aObject,propinfo,Result);
  683. except
  684. on E : Exception do
  685. begin
  686. raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s" : %s',[aObject.ClassName,e.Message]);
  687. end;
  688. end;
  689. end;
  690. {$ENDIF}
  691. function TRTTIJson.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
  692. var
  693. propname : string;
  694. cname : string;
  695. begin
  696. Result := True;
  697. propname := aPropertyName.ToLower;
  698. if IsGenericList(aObject) then
  699. begin
  700. if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
  701. end
  702. else if (propname = 'refcount') then Result := False;
  703. end;
  704. function TRTTIJson.IsGenericList(aObject : TObject) : Boolean;
  705. var
  706. cname : string;
  707. begin
  708. cname := aObject.ClassName;
  709. Result := (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList'));
  710. end;
  711. function TRTTIJson.GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
  712. var
  713. pinfo : PPropInfo;
  714. begin
  715. Result := nil;
  716. pinfo := GetPropInfo(Instance,PropertyName);
  717. case pinfo.PropType^.Kind of
  718. tkInteger : Result := GetOrdProp(Instance,pinfo);
  719. tkInt64 : Result := GetInt64Prop(Instance,PropertyName);
  720. tkFloat : Result := GetFloatProp(Instance,PropertyName);
  721. tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
  722. {$IFDEF FPC}
  723. tkWString : Result := GetWideStrProp(Instance,PropertyName);
  724. tkSString,
  725. tkAString,
  726. {$ELSE}
  727. tkWString,
  728. {$ENDIF}
  729. tkLString : Result := GetStrProp(Instance,pinfo);
  730. {$IFDEF FPC}
  731. tkEnumeration : Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName));
  732. {$ELSE}
  733. tkEnumeration : Result := GetEnumName(@pinfo.PropType,GetOrdProp(Instance,PropertyName));
  734. {$ENDIF}
  735. tkSet : Result := GetSetProp(Instance,pinfo,True);
  736. {$IFNDEF FPC}
  737. tkClass :
  738. {$ELSE}
  739. tkBool : Result := Boolean(GetOrdProp(Instance,pinfo));
  740. tkObject :
  741. {$ENDIF} Result := GetObjectProp(Instance,pinfo);
  742. tkDynArray : Result := GetDynArrayProp(Instance,pinfo);
  743. end;
  744. end;
  745. procedure TRTTIJson.SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue);
  746. var
  747. pinfo : PPropInfo;
  748. begin
  749. pinfo := GetPropInfo(Instance,PropertyName);
  750. SetPropertyValue(Instance,pinfo,aValue);
  751. end;
  752. procedure TRTTIJson.SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue);
  753. begin
  754. case aPropInfo.PropType^.Kind of
  755. tkInteger : SetOrdProp(Instance,aPropInfo,aValue.AsInteger);
  756. tkInt64 : SetInt64Prop(Instance,aPropInfo,aValue.AsInt64);
  757. tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
  758. tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  759. {$IFDEF FPC}
  760. tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
  761. tkSString,
  762. tkAString,
  763. {$ELSE}
  764. tkWString,
  765. {$ENDIF}
  766. tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
  767. {$IFDEF FPC}
  768. tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  769. tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
  770. {$ENDIF}
  771. tkEnumeration : SetEnumProp(Instance,aPropInfo,aValue.AsString);
  772. {$IFNDEF FPC}
  773. tkClass :
  774. {$ELSE}
  775. tkObject :
  776. {$ENDIF} SetObjectProp(Instance,aPropInfo,aValue.AsObject);
  777. end;
  778. end;
  779. {$IFDEF FPC}
  780. procedure TRTTIJson.LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  781. type
  782. TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
  783. const
  784. Delims = [' ', ',', '[', ']'];
  785. var
  786. TypeInfo: PTypeInfo;
  787. W: Cardinal;
  788. I, N: Integer;
  789. Count: Integer;
  790. EnumName: string;
  791. begin
  792. W := 0;
  793. TypeInfo := GetTypeData(GetPropType(aPropInfo))^.CompType;
  794. Count := WordCount(aValue, Delims);
  795. for N := 1 to Count do
  796. begin
  797. EnumName := ExtractWord(N, aValue, Delims);
  798. try
  799. I := GetEnumValue(TypeInfo, EnumName);
  800. if I >= 0 then Include(TCardinalSet(W),I);
  801. except
  802. end;
  803. end;
  804. SetOrdProp(aInstance,aPropInfo,W);
  805. end;
  806. {$ENDIF}
  807. function TRTTIJson.Serialize(aObject: TObject): TJSONObject;
  808. var
  809. ctx: TRttiContext;
  810. {$IFNDEF FPC}
  811. attr : TCustomAttribute;
  812. comment : string;
  813. {$ENDIF}
  814. rType: TRttiType;
  815. rProp: TRttiProperty;
  816. jpair : TJSONPair;
  817. ExcludeSerialize : Boolean;
  818. propertyname : string;
  819. //listtype : TRttiType;
  820. //listprop : TRttiProperty;
  821. //listvalue : TValue;
  822. begin
  823. if (aObject = nil) then
  824. begin
  825. Result := nil;
  826. Exit;
  827. end;
  828. Result := TJSONObject.Create;
  829. try
  830. rType := ctx.GetType(aObject.ClassInfo);
  831. try
  832. //s := rType.ToString;
  833. for rProp in rType.GetProperties do
  834. begin
  835. ExcludeSerialize := False;
  836. propertyname := rProp.Name;
  837. {$IFNDEF FPC}
  838. comment := '';
  839. for attr in rProp.GetAttributes do
  840. begin
  841. if attr is TNotSerializableProperty then ExcludeSerialize := True
  842. else if attr is TCommentProperty then comment := TCommentProperty(attr).Comment
  843. else if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  844. end;
  845. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  846. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  847. {$ENDIF}
  848. begin
  849. if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
  850. begin
  851. //add comment as pair
  852. {$IFNDEF FPC}
  853. if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
  854. {$ENDIF}
  855. //listtype := ctx.GetType(rProp.GetValue(aObject).TypeInfo);
  856. //if (listtype.ClassParent.ClassName.StartsWith('TObjectList')) then
  857. //begin
  858. // jpair := Serialize(propertyname,rProp.GetValue(aObject));
  859. // Result.AddPair(propertyname,(jpair.JsonValue as TJSONObject).GetValue('List').Clone as TJsonValue);
  860. // jpair.Free;
  861. //listtype := ctx.GetType(rProp.GetValue(aObject).AsObject.ClassInfo);
  862. //listprop := listtype.GetProperty('List');
  863. //listvalue := listprop.GetValue(aObject);
  864. //jpair := Serialize('Groups',listvalue);
  865. //if jpair <> nil then Result.AddPair(jpair)
  866. // else jpair.Free;
  867. //Exit;
  868. //end
  869. //else
  870. begin
  871. {$IFNDEF FPC}
  872. jpair := Serialize(propertyname,rProp.GetValue(aObject));
  873. {$ELSE}
  874. jpair := Serialize(aObject,rProp.PropertyType.TypeKind,propertyname);
  875. {$ENDIF}
  876. //s := jpair.JsonValue.ToString;
  877. if jpair <> nil then
  878. begin
  879. Result.AddPair(jpair);
  880. end
  881. else jpair.Free;
  882. end;
  883. //Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
  884. //s := Result.ToJSON;
  885. end;
  886. end;
  887. end;
  888. finally
  889. ctx.Free;
  890. end;
  891. except
  892. on E : Exception do
  893. begin
  894. Result.Free;
  895. raise EJsonSerializeError.CreateFmt('Serialize error object "%s" : %s',[aObject.ClassName,e.Message]);
  896. end;
  897. end;
  898. end;
  899. function TRTTIJson.GetValue(aAddr: Pointer; aType: TRTTIType): TValue;
  900. begin
  901. TValue.Make(aAddr,aType.Handle,Result);
  902. end;
  903. function TRTTIJson.GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue;
  904. begin
  905. TValue.Make(aAddr,aTypeInfo,Result);
  906. end;
  907. {$IFNDEF FPC}
  908. function TRTTIJson.Serialize(const aName : string; aValue : TValue) : TJSONPair;
  909. var
  910. ctx: TRttiContext;
  911. rRec : TRttiRecordType;
  912. rField : TRttiField;
  913. rDynArray : TRTTIDynamicArrayType;
  914. json : TJSONObject;
  915. jArray : TJSONArray;
  916. jPair : TJSONPair;
  917. jValue : TJSONValue;
  918. i : Integer;
  919. s : string;
  920. begin
  921. Result := TJSONPair.Create(aName,nil);
  922. //Result.JsonString := TJSONString(aName);
  923. try
  924. case avalue.Kind of
  925. tkDynArray :
  926. begin
  927. jArray := TJSONArray.Create;
  928. rDynArray := ctx.GetType(aValue.TypeInfo) as TRTTIDynamicArrayType;
  929. try
  930. for i := 0 to aValue.GetArrayLength - 1 do
  931. begin
  932. jPair := Serialize(aName,GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType));
  933. try
  934. //jValue := TJsonValue(jPair.JsonValue.Clone);
  935. jValue := jPair.JsonValue;
  936. jArray.AddElement(jValue);
  937. if jPair.JsonValue <> nil then jPair.JsonValue.Owned := False;
  938. finally
  939. jPair.Free;
  940. if jValue <> nil then jValue.Owned := True;
  941. end;
  942. end;
  943. Result.JsonValue := jArray;
  944. finally
  945. ctx.Free;
  946. end;
  947. end;
  948. tkClass :
  949. begin
  950. Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
  951. end;
  952. tkString, tkLString, tkWString, tkUString :
  953. begin
  954. Result.JsonValue := TJSONString.Create(aValue.AsString);
  955. end;
  956. tkChar, tkWChar :
  957. begin
  958. Result.JsonValue := TJSONString.Create(aValue.AsString);
  959. end;
  960. tkInteger :
  961. begin
  962. Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  963. end;
  964. tkInt64 :
  965. begin
  966. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  967. end;
  968. tkFloat :
  969. begin
  970. if aValue.TypeInfo = TypeInfo(TDateTime) then
  971. begin
  972. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(aValue.AsExtended));
  973. end
  974. else if aValue.TypeInfo = TypeInfo(TDate) then
  975. begin
  976. Result.JsonValue := TJSONString.Create(DateToStr(aValue.AsExtended));
  977. end
  978. else if aValue.TypeInfo = TypeInfo(TTime) then
  979. begin
  980. Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
  981. end
  982. else
  983. begin
  984. Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  985. end;
  986. end;
  987. tkEnumeration :
  988. begin
  989. if (aValue.TypeInfo = System.TypeInfo(Boolean)) then
  990. begin
  991. Result.JsonValue := TJSONBool.Create(aValue.AsBoolean);
  992. end
  993. else
  994. begin
  995. //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
  996. Result.JsonValue := TJSONString.Create(aValue.ToString);
  997. end;
  998. end;
  999. tkSet :
  1000. begin
  1001. Result.JsonValue := TJSONString.Create(aValue.ToString);
  1002. end;
  1003. tkRecord :
  1004. begin
  1005. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1006. try
  1007. json := TJSONObject.Create;
  1008. for rField in rRec.GetFields do
  1009. begin
  1010. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1011. end;
  1012. Result.JsonValue := json;
  1013. finally
  1014. ctx.Free;
  1015. end;
  1016. end;
  1017. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1018. begin
  1019. //skip these properties
  1020. FreeAndNil(Result);
  1021. end
  1022. else
  1023. begin
  1024. raise EJsonSerializeError.CreateFmt(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]);
  1025. end;
  1026. end;
  1027. except
  1028. on E : Exception do
  1029. begin
  1030. Result.Free;
  1031. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1032. end;
  1033. end;
  1034. end;
  1035. {$ELSE}
  1036. function TRTTIJson.GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  1037. begin
  1038. Result := aPropInfo^.PropType;
  1039. end;
  1040. function TRTTIJson.FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  1041. const
  1042. Precisions: array[TFloatType] of Integer = (7, 15, 18, 18, 19);
  1043. var
  1044. fsettings : TFormatSettings;
  1045. begin
  1046. fsettings := FormatSettings;
  1047. Result := StringReplace(FloatToStrF(GetFloatProp(aObject, aPropInfo), ffGeneral,
  1048. Precisions[GetTypeData(GetPropType(aPropInfo))^.FloatType],0),
  1049. '.',fsettings.DecimalSeparator,[rfReplaceAll]);
  1050. end;
  1051. function TRTTIJson.Serialize(const aName : string; aValue : TValue) : TJSONPair;
  1052. begin
  1053. Result := TJSONPair.Create(aName,nil);
  1054. //Result.JsonString := TJSONString(aName);
  1055. try
  1056. case avalue.Kind of
  1057. tkInteger, tkInt64 :
  1058. begin
  1059. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  1060. end;
  1061. else
  1062. begin
  1063. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1064. end;
  1065. end;
  1066. except
  1067. Result.Free;
  1068. end;
  1069. end;
  1070. function TRTTIJson.Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  1071. var
  1072. propinfo : PPropInfo;
  1073. jArray : TJsonArray;
  1074. jPair : TJsonPair;
  1075. jValue : TJsonValue;
  1076. i : Integer;
  1077. pArr : Pointer;
  1078. rValue : TValue;
  1079. rItemValue : TValue;
  1080. len : Integer;
  1081. begin
  1082. try
  1083. Result := TJSONPair.Create(aPropertyName,nil);
  1084. propinfo := GetPropInfo(aObject,aPropertyName);
  1085. //case propinfo.PropType.Kind of
  1086. case aType of
  1087. tkDynArray :
  1088. begin
  1089. len := 0;
  1090. jArray := TJSONArray.Create;
  1091. try
  1092. pArr := GetDynArrayProp(aObject,aPropertyName);
  1093. TValue.Make(@pArr,propinfo.PropType, rValue);
  1094. if rValue.IsArray then len := rValue.GetArrayLength;
  1095. for i := 0 to len - 1 do
  1096. begin
  1097. rItemValue := rValue.GetArrayElement(i);
  1098. jPair := Serialize(aPropertyName,rItemValue);
  1099. try
  1100. //jValue := TJsonValue(jPair.JsonValue.Clone);
  1101. jValue := jPair.JsonValue;
  1102. jArray.Add(jValue);
  1103. //jPair.JsonValue.Owned := False;
  1104. finally
  1105. jPair.Free;
  1106. //jValue.Owned := True;
  1107. end;
  1108. end;
  1109. Result.JsonValue := jArray;
  1110. finally
  1111. DynArrayClear(pArr,propinfo.PropType);
  1112. end;
  1113. end;
  1114. tkClass :
  1115. begin
  1116. Result.JsonValue := TJSONValue(Serialize(GetObjectProp(aObject,aPropertyName)));
  1117. end;
  1118. tkString, tkLString, tkWString, tkUString, tkAString :
  1119. begin
  1120. Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
  1121. end;
  1122. tkChar, tkWChar :
  1123. begin
  1124. Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
  1125. end;
  1126. tkInteger :
  1127. begin
  1128. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1129. end;
  1130. tkInt64 :
  1131. begin
  1132. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1133. end;
  1134. tkFloat :
  1135. begin
  1136. if propinfo.PropType = TypeInfo(TDateTime) then
  1137. begin
  1138. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
  1139. end
  1140. else if propinfo.PropType = TypeInfo(TDate) then
  1141. begin
  1142. Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
  1143. end
  1144. else if propinfo.PropType = TypeInfo(TTime) then
  1145. begin
  1146. Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
  1147. end
  1148. else
  1149. begin
  1150. //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
  1151. Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
  1152. end;
  1153. end;
  1154. tkEnumeration,tkBool :
  1155. begin
  1156. if (propinfo.PropType = System.TypeInfo(Boolean)) then
  1157. begin
  1158. Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
  1159. end
  1160. else
  1161. begin
  1162. Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)));
  1163. //Result.JsonValue := TJSONString.Create(aValue.ToString);
  1164. end;
  1165. end;
  1166. tkSet :
  1167. begin
  1168. Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
  1169. end;
  1170. {$IFNDEF FPC}
  1171. tkRecord :
  1172. begin
  1173. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1174. try
  1175. json := TJSONObject.Create;
  1176. for rField in rRec.GetFields do
  1177. begin
  1178. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1179. end;
  1180. Result.JsonValue := json;
  1181. finally
  1182. ctx.Free;
  1183. end;
  1184. end;
  1185. {$ENDIF}
  1186. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1187. begin
  1188. //skip these properties
  1189. FreeAndNil(Result);
  1190. end
  1191. else
  1192. begin
  1193. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1194. end;
  1195. end;
  1196. except
  1197. on E : Exception do
  1198. begin
  1199. Result.Free;
  1200. {$IFNDEF FPC}
  1201. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1202. {$ENDIF}
  1203. end;
  1204. end;
  1205. end;
  1206. {$ENDIF}
  1207. { TJsonSerializer}
  1208. constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel);
  1209. begin
  1210. {$IFDEF FPC}
  1211. if aSerializeLevel = TSerializeLevel.slPublicProperty then raise EJsonSerializeError.Create('FreePascal RTTI only supports published properties');
  1212. {$ENDIF}
  1213. fSerializeLevel := aSerializeLevel;
  1214. fRTTIJson := TRTTIJson.Create(aSerializeLevel);
  1215. end;
  1216. function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObject;
  1217. var
  1218. json: TJSONObject;
  1219. begin
  1220. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1221. try
  1222. Result := fRTTIJson.DeserializeClass(aType,json);
  1223. finally
  1224. json.Free;
  1225. end;
  1226. end;
  1227. destructor TJsonSerializer.Destroy;
  1228. begin
  1229. fRTTIJson.Free;
  1230. inherited;
  1231. end;
  1232. function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TObject;
  1233. var
  1234. json: TJSONObject;
  1235. begin
  1236. json := TJsonObject(TJSONObject.ParseJSONValue(aJson,True));
  1237. try
  1238. Result := fRTTIJson.DeserializeObject(aObject,json);
  1239. finally
  1240. json.Free;
  1241. end;
  1242. end;
  1243. function TJsonSerializer.ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  1244. var
  1245. json: TJSONObject;
  1246. begin
  1247. json := fRTTIJson.Serialize(aObject);
  1248. try
  1249. Result := json.ToJSON;
  1250. if aIndent then Result := TJsonUtils.JsonFormat(Result);
  1251. finally
  1252. json.Free;
  1253. end;
  1254. end;
  1255. {$IFNDEF FPC}
  1256. { TCommentProperty }
  1257. constructor TCommentProperty.Create(const aComment: string);
  1258. begin
  1259. fComment := aComment;
  1260. end;
  1261. { TCustomNameProperty }
  1262. constructor TCustomNameProperty.Create(const aName: string);
  1263. begin
  1264. fName := aName;
  1265. end;
  1266. {$ENDIF}
  1267. end.