Quick.Json.Serializer.pas 44 KB

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