2
0

Quick.Json.Serializer.pas 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  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. tkInteger, tkInt64 :
  1100. begin
  1101. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  1102. end;
  1103. else
  1104. begin
  1105. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1106. end;
  1107. end;
  1108. except
  1109. Result.Free;
  1110. end;
  1111. end;
  1112. function TRTTIJson.Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  1113. var
  1114. propinfo : PPropInfo;
  1115. jArray : TJsonArray;
  1116. jPair : TJsonPair;
  1117. jValue : TJsonValue;
  1118. i : Integer;
  1119. pArr : Pointer;
  1120. rValue : TValue;
  1121. rItemValue : TValue;
  1122. len : Integer;
  1123. begin
  1124. try
  1125. Result := TJSONPair.Create(aPropertyName,nil);
  1126. propinfo := GetPropInfo(aObject,aPropertyName);
  1127. //case propinfo.PropType.Kind of
  1128. case aType of
  1129. tkDynArray :
  1130. begin
  1131. len := 0;
  1132. jArray := TJSONArray.Create;
  1133. try
  1134. pArr := GetDynArrayProp(aObject,aPropertyName);
  1135. TValue.Make(@pArr,propinfo.PropType, rValue);
  1136. if rValue.IsArray then
  1137. begin
  1138. len := rValue.GetArrayLength;
  1139. for i := 0 to len - 1 do
  1140. begin
  1141. rItemValue := rValue.GetArrayElement(i);
  1142. jPair := Serialize(aPropertyName,rItemValue);
  1143. try
  1144. //jValue := TJsonValue(jPair.JsonValue.Clone);
  1145. jValue := jPair.JsonValue;
  1146. jArray.Add(jValue);
  1147. //jPair.JsonValue.Owned := False;
  1148. finally
  1149. jPair.Free;
  1150. //jValue.Owned := True;
  1151. end;
  1152. end;
  1153. end;
  1154. Result.JsonValue := jArray;
  1155. finally
  1156. DynArrayClear(pArr,propinfo.PropType);
  1157. end;
  1158. end;
  1159. tkClass :
  1160. begin
  1161. Result.JsonValue := TJSONValue(Serialize(GetObjectProp(aObject,aPropertyName)));
  1162. end;
  1163. tkString, tkLString, tkWString, tkUString, tkAString :
  1164. begin
  1165. Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
  1166. end;
  1167. tkChar, tkWChar :
  1168. begin
  1169. Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
  1170. end;
  1171. tkInteger :
  1172. begin
  1173. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1174. end;
  1175. tkInt64 :
  1176. begin
  1177. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1178. end;
  1179. tkFloat :
  1180. begin
  1181. if propinfo.PropType = TypeInfo(TDateTime) then
  1182. begin
  1183. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
  1184. end
  1185. else if propinfo.PropType = TypeInfo(TDate) then
  1186. begin
  1187. Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
  1188. end
  1189. else if propinfo.PropType = TypeInfo(TTime) then
  1190. begin
  1191. Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
  1192. end
  1193. else
  1194. begin
  1195. //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
  1196. Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
  1197. end;
  1198. end;
  1199. tkEnumeration,tkBool :
  1200. begin
  1201. if (propinfo.PropType = System.TypeInfo(Boolean)) then
  1202. begin
  1203. Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
  1204. end
  1205. else
  1206. begin
  1207. if fUseEnumNames then Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)))
  1208. else Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1209. //Result.JsonValue := TJSONString.Create(aValue.ToString);
  1210. end;
  1211. end;
  1212. tkSet :
  1213. begin
  1214. Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
  1215. end;
  1216. {$IFNDEF FPC}
  1217. tkRecord :
  1218. begin
  1219. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1220. try
  1221. json := TJSONObject.Create;
  1222. for rField in rRec.GetFields do
  1223. begin
  1224. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1225. end;
  1226. Result.JsonValue := json;
  1227. finally
  1228. ctx.Free;
  1229. end;
  1230. end;
  1231. {$ENDIF}
  1232. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1233. begin
  1234. //skip these properties
  1235. FreeAndNil(Result);
  1236. end
  1237. else
  1238. begin
  1239. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1240. end;
  1241. end;
  1242. except
  1243. on E : Exception do
  1244. begin
  1245. Result.Free;
  1246. {$IFNDEF FPC}
  1247. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1248. {$ENDIF}
  1249. end;
  1250. end;
  1251. end;
  1252. {$ENDIF}
  1253. { TJsonSerializer}
  1254. constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel);
  1255. begin
  1256. {$IFDEF FPC}
  1257. if aSerializeLevel = TSerializeLevel.slPublicProperty then raise EJsonSerializeError.Create('FreePascal RTTI only supports published properties');
  1258. {$ENDIF}
  1259. fSerializeLevel := aSerializeLevel;
  1260. fUseEnumNames := True;
  1261. fRTTIJson := TRTTIJson.Create(aSerializeLevel);
  1262. fRTTIJson.UseEnumNames := fUseEnumNames;
  1263. end;
  1264. function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObject;
  1265. var
  1266. json: TJSONObject;
  1267. begin
  1268. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1269. try
  1270. Result := fRTTIJson.DeserializeClass(aType,json);
  1271. finally
  1272. json.Free;
  1273. end;
  1274. end;
  1275. destructor TJsonSerializer.Destroy;
  1276. begin
  1277. fRTTIJson.Free;
  1278. inherited;
  1279. end;
  1280. function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TObject;
  1281. var
  1282. json: TJSONObject;
  1283. begin
  1284. json := TJsonObject(TJSONObject.ParseJSONValue(aJson,True));
  1285. try
  1286. Result := fRTTIJson.DeserializeObject(aObject,json);
  1287. finally
  1288. json.Free;
  1289. end;
  1290. end;
  1291. function TJsonSerializer.ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  1292. var
  1293. json: TJSONObject;
  1294. begin
  1295. json := fRTTIJson.Serialize(aObject);
  1296. try
  1297. Result := json.ToJSON;
  1298. if aIndent then Result := TJsonUtils.JsonFormat(Result);
  1299. finally
  1300. json.Free;
  1301. end;
  1302. end;
  1303. procedure TJsonSerializer.SetUseEnumNames(const Value: Boolean);
  1304. begin
  1305. fUseEnumNames := Value;
  1306. if Assigned(fRTTIJson) then fRTTIJson.UseEnumNames := Value;
  1307. end;
  1308. {$IFNDEF FPC}
  1309. { TCommentProperty }
  1310. constructor TCommentProperty.Create(const aComment: string);
  1311. begin
  1312. fComment := aComment;
  1313. end;
  1314. { TCustomNameProperty }
  1315. constructor TCustomNameProperty.Create(const aName: string);
  1316. begin
  1317. fName := aName;
  1318. end;
  1319. {$ENDIF}
  1320. end.