Quick.Json.Serializer.pas 44 KB

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