Quick.Json.Serializer.pas 40 KB

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