Quick.Json.Serializer.pas 41 KB

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