Quick.Json.Serializer.pas 41 KB

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