Quick.Json.Serializer.pas 40 KB

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