Quick.Json.Serializer.pas 40 KB

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