Quick.Json.Serializer.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708
  1. { ***************************************************************************
  2. Copyright (c) 2015-2020 Kike Pérez
  3. Unit : Quick.JSON.Serializer
  4. Description : Json Serializer
  5. Author : Kike Pérez
  6. Version : 1.11
  7. Created : 21/05/2018
  8. Modified : 07/04/2020
  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 DELPHIRX10_UP}
  42. {$ENDIF}
  43. Variants,
  44. {$ENDIF}
  45. Quick.RTTI.Utils,
  46. DateUtils,
  47. Quick.Commons,
  48. Quick.JSON.Utils;
  49. type
  50. EJsonSerializeError = class(Exception);
  51. EJsonDeserializeError = class(Exception);
  52. {$IFNDEF FPC}
  53. TNotSerializableProperty = class(TCustomAttribute);
  54. TCommentProperty = class(TCustomAttribute)
  55. private
  56. fComment : string;
  57. public
  58. constructor Create(const aComment: string);
  59. property Comment : string read fComment;
  60. end;
  61. TCustomNameProperty = class(TCustomAttribute)
  62. private
  63. fName : string;
  64. public
  65. constructor Create(const aName: string);
  66. property Name : string read fName;
  67. end;
  68. {$ENDIF}
  69. IJsonSerializer = interface
  70. ['{CA26F7AE-F1FE-41BE-9C23-723A687F60D1}']
  71. function JsonToObject(aType: TClass; const aJson: string): TObject; overload;
  72. function JsonToObject(aObject: TObject; const aJson: string): TObject; overload;
  73. function ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  74. function ValueToJson(const aValue : TValue; aIndent : Boolean = False) : string;
  75. end;
  76. TSerializeLevel = (slPublicProperty, slPublishedProperty);
  77. TRTTIJson = class
  78. private
  79. fSerializeLevel : TSerializeLevel;
  80. fUseEnumNames : Boolean;
  81. fUseJsonCaseSense : Boolean;
  82. function GetValue(aAddr: Pointer; aType: TRTTIType): TValue; overload;
  83. function GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue; overload;
  84. function IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
  85. function IsGenericList(aObject : TObject) : Boolean;
  86. function IsGenericXArray(const aClassName : string) : Boolean;
  87. function GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
  88. function GetPropertyValueFromObject(Instance : TObject; const PropertyName : string) : TValue;
  89. {$IFNDEF FPC}
  90. function GetFieldValueFromRecord(const aValue : TValue; const FieldName : string) : TValue;
  91. {$ENDIF}
  92. procedure SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue); overload;
  93. procedure SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue); overload;
  94. {$IFDEF FPC}
  95. function FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  96. function GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  97. procedure LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  98. {$ENDIF}
  99. public
  100. constructor Create(aSerializeLevel : TSerializeLevel; aUseEnumNames : Boolean = True);
  101. property UseEnumNames : Boolean read fUseEnumNames write fUseEnumNames;
  102. property UseJsonCaseSense : Boolean read fUseJsonCaseSense write fUseJsonCaseSense;
  103. function GetJsonPairValueByName(aJson : TJSONObject; const aName : string) : TJsonValue;
  104. function GetJsonPairByName(aJson : TJSONObject; const aName : string) : TJSONPair;
  105. //serialize methods
  106. function SerializeValue(const aValue : TValue) : TJSONValue;
  107. function SerializeObject(aObject : TObject) : TJSONObject; overload;
  108. {$IFNDEF FPC}
  109. function SerializeDynArray(const aValue: TValue) : TJsonArray;
  110. function SerializeRecord(const aValue : TValue) : TJSONValue;
  111. {$ELSE}
  112. function SerializeObject(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  113. {$ENDIF}
  114. //deserialize methods
  115. function DeserializeClass(aType : TClass; const aJson : TJSONObject) : TObject;
  116. function DeserializeObject(aObject : TObject; const aJson : TJSONObject) : TObject; overload;
  117. function DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject; overload;
  118. {$IFNDEF FPC}
  119. function DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
  120. function DeserializeDynArray(aTypeInfo : PTypeInfo; aObject : TObject; const aJsonArray: TJSONArray) : TValue;
  121. function DeserializeRecord(const aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
  122. function DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
  123. procedure DeserializeXArray(Instance : TObject; aRecord : TValue; aProperty : TRttiProperty; const aPropertyName : string; aJson : TJsonObject);
  124. {$ELSE}
  125. function DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
  126. procedure DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
  127. {$ENDIF}
  128. end;
  129. TJsonSerializer = class(TInterfacedObject,IJsonSerializer)
  130. strict private
  131. fSerializeLevel : TSerializeLevel;
  132. fUseEnumNames : Boolean;
  133. fUseJsonCaseSense : Boolean;
  134. fRTTIJson : TRTTIJson;
  135. private
  136. procedure SetUseEnumNames(const Value: Boolean);
  137. procedure SetUseJsonCaseSense(const Value: Boolean);
  138. public
  139. constructor Create(aSerializeLevel: TSerializeLevel; aUseEnumNames : Boolean = True);
  140. destructor Destroy; override;
  141. property SerializeLevel : TSerializeLevel read fSerializeLevel;
  142. property UseEnumNames : Boolean read fUseEnumNames write SetUseEnumNames;
  143. property UseJsonCaseSense : Boolean read fUseJsonCaseSense write SetUseJsonCaseSense;
  144. function JsonToObject(aType : TClass; const aJson: string) : TObject; overload;
  145. function JsonToObject(aObject : TObject; const aJson: string) : TObject; overload;
  146. function ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  147. function ObjectToJsonString(aObject : TObject; aIndent : Boolean = False): string;
  148. function ValueToJson(const aValue : TValue; aIndent : Boolean = False) : string;
  149. function ValueToJsonString(const aValue : TValue; aIndent : Boolean = False) : string;
  150. function ArrayToJson<T>(aArray : TArray<T>; aIndent : Boolean = False) : string;
  151. function ArrayToJsonString<T>(aArray : TArray<T>; aIndent : Boolean = False) : string;
  152. {$IFNDEF FPC}
  153. function JsonToArray<T>(const aJson : string) : TArray<T>;
  154. function JsonToValue(const aJson: string): TValue;
  155. {$ENDIF}
  156. end;
  157. EJsonSerializerError = class(Exception);
  158. PPByte = ^PByte;
  159. resourcestring
  160. cNotSupportedDataType = 'Not supported data type "%s"';
  161. cSerializeObjectError = 'Serialize object "%s" error: %s';
  162. cSerializePropertyError = 'Property "%s" ("%s")';
  163. cNotSerializable = 'Object is not serializable';
  164. cNotValidJson = 'Not a valid Json';
  165. implementation
  166. uses
  167. Generics.Collections;
  168. { TRTTIJson }
  169. {$IFNDEF FPC}
  170. function TRTTIJson.DeserializeDynArray(aTypeInfo: PTypeInfo; aObject: TObject; const aJsonArray: TJSONArray) : TValue;
  171. var
  172. rType: PTypeInfo;
  173. len: NativeInt;
  174. pArr: Pointer;
  175. rItemValue: TValue;
  176. i: Integer;
  177. objClass: TClass;
  178. ctx : TRttiContext;
  179. json : TJSONObject;
  180. rDynArray : TRttiDynamicArrayType;
  181. propObj : TObject;
  182. begin
  183. if GetTypeData(aTypeInfo).DynArrElType = nil then Exit;
  184. if not assigned(aJsonArray) then Exit;
  185. len := aJsonArray.Count;
  186. rType := GetTypeData(aTypeInfo).DynArrElType^;
  187. pArr := nil;
  188. DynArraySetLength(pArr,aTypeInfo, 1, @len);
  189. try
  190. TValue.Make(@pArr,aTypeInfo, Result);
  191. rDynArray := ctx.GetType(Result.TypeInfo) as TRTTIDynamicArrayType;
  192. for i := 0 to aJsonArray.Count - 1 do
  193. begin
  194. rItemValue := nil;
  195. case rType.Kind of
  196. tkClass :
  197. begin
  198. if aJsonArray.Items[i] is TJSONObject then
  199. begin
  200. propObj := GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i, rDynArray.ElementType).AsObject;
  201. if propObj = nil then
  202. begin
  203. objClass := rType.TypeData.ClassType;
  204. rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
  205. end
  206. else
  207. begin
  208. DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
  209. end;
  210. end;
  211. end;
  212. tkRecord :
  213. begin
  214. json := TJSONObject(aJsonArray.Items[i]);
  215. rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
  216. rDynArray.ElementType),aObject,json);
  217. end;
  218. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  219. begin
  220. //skip these properties
  221. end
  222. else
  223. begin
  224. rItemValue := DeserializeType(aObject,rType.Kind,aTypeInfo,aJsonArray.Items[i].Value);
  225. end;
  226. end;
  227. if not rItemValue.IsEmpty then Result.SetArrayElement(i,rItemValue);
  228. end;
  229. //aProperty.SetValue(aObject,rValue);
  230. finally
  231. DynArrayClear(pArr,aTypeInfo);
  232. end;
  233. end;
  234. {$ELSE}
  235. procedure TRTTIJson.DeserializeDynArray(aTypeInfo: PTypeInfo; const aPropertyName : string; aObject: TObject; const aJsonArray: TJSONArray);
  236. var
  237. rType: PTypeInfo;
  238. len: NativeInt;
  239. pArr: Pointer;
  240. rItemValue: TValue;
  241. i: Integer;
  242. objClass: TClass;
  243. propObj : TObject;
  244. rValue : TValue;
  245. begin
  246. if GetTypeData(aTypeInfo).ElType2 = nil then Exit;
  247. len := aJsonArray.Count;
  248. rType := GetTypeData(aTypeInfo).ElType2;
  249. pArr := nil;
  250. DynArraySetLength(pArr,aTypeInfo, 1, @len);
  251. try
  252. TValue.Make(@pArr,aTypeInfo, rValue);
  253. for i := 0 to aJsonArray.Count - 1 do
  254. begin
  255. rItemValue := nil;
  256. case rType.Kind of
  257. tkClass :
  258. begin
  259. if aJsonArray.Items[i] is TJSONObject then
  260. begin
  261. propObj := GetValue(PPByte(rValue.GetReferenceToRawData)^ +GetTypeData(aTypeInfo).elSize * i, GetTypeData(aTypeInfo).ElType2).AsObject;
  262. if propObj = nil then
  263. begin
  264. objClass := GetTypeData(aTypeInfo).ClassType;
  265. rItemValue := DeserializeClass(objClass, TJSONObject(aJsonArray.Items[i]));
  266. end
  267. else
  268. begin
  269. DeserializeObject(propObj,TJSONObject(aJsonArray.Items[i]));
  270. end;
  271. end;
  272. end;
  273. tkRecord :
  274. begin
  275. {json := TJSONObject(aJsonArray.Items[i]);
  276. rItemValue := DeserializeRecord(GetValue(PPByte(Result.GetReferenceToRawData)^ +rDynArray.ElementType.TypeSize * i,
  277. rDynArray.ElementType),aObject,json); }
  278. end;
  279. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  280. begin
  281. //skip these properties
  282. end
  283. else
  284. begin
  285. rItemValue := DeserializeType(aObject,GetTypeData(aTypeInfo).ElType2.Kind,aPropertyName,aJsonArray.Items[i].Value);
  286. end;
  287. end;
  288. if not rItemValue.IsEmpty then rValue.SetArrayElement(i,rItemValue);
  289. end;
  290. //aProperty.SetValue(aObject,rValue);
  291. SetDynArrayProp(aObject,GetPropInfo(aObject,aPropertyName),pArr);
  292. finally
  293. DynArrayClear(pArr,aTypeInfo);
  294. end;
  295. end;
  296. {$ENDIF}
  297. {$IFNDEF FPC}
  298. function TRTTIJson.DeserializeRecord(const aRecord : TValue; aObject : TObject; const aJson : TJSONObject) : TValue;
  299. var
  300. ctx : TRttiContext;
  301. rRec : TRttiRecordType;
  302. rField : TRttiField;
  303. rValue : TValue;
  304. member : TJsonValue;
  305. jArray : TJSONArray;
  306. json : TJSONObject;
  307. objClass : TClass;
  308. propobj : TObject;
  309. begin
  310. rRec := ctx.GetType(aRecord.TypeInfo).AsRecord;
  311. for rField in rRec.GetFields do
  312. begin
  313. rValue := nil;
  314. //member := TJSONPair(aJson.GetValue(rField.Name));
  315. member := GetJsonPairValueByName(aJson,rField.Name);
  316. if member <> nil then
  317. case rField.FieldType.TypeKind of
  318. tkDynArray :
  319. begin
  320. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  321. try
  322. rValue := DeserializeDynArray(rField.FieldType.Handle,aObject,jArray);
  323. finally
  324. jArray.Free;
  325. end;
  326. end;
  327. tkClass :
  328. begin
  329. //if (member.JsonValue is TJSONObject) then
  330. begin
  331. propobj := rField.GetValue(@aRecord).AsObject;
  332. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  333. try
  334. if propobj = nil then
  335. begin
  336. objClass := rField.FieldType.Handle^.TypeData.ClassType;// aProperty.PropertyType.Handle^.TypeData.ClassType;
  337. rValue := DeserializeClass(objClass,json);
  338. end
  339. else
  340. begin
  341. DeserializeObject(propobj,json);
  342. end;
  343. finally
  344. json.Free;
  345. end;
  346. end
  347. end;
  348. tkRecord :
  349. begin
  350. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  351. try
  352. rValue := DeserializeRecord(rField.GetValue(aRecord.GetReferenceToRawData),aObject,json);
  353. finally
  354. json.Free;
  355. end;
  356. end
  357. else
  358. begin
  359. //rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.ToJson);
  360. //avoid return unicode escaped chars if string
  361. if rField.FieldType.TypeKind in [tkString, tkLString, tkWString, tkUString] then
  362. {$IFDEF DELPHIRX10_UP}
  363. rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,TJsonValue(member).value)
  364. {$ELSE}
  365. rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.JsonString.ToString)
  366. {$ENDIF}
  367. else rValue := DeserializeType(aObject,rField.FieldType.TypeKind,rField.FieldType.Handle,member.ToJSON);
  368. end;
  369. end;
  370. if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
  371. end;
  372. Result := aRecord;
  373. end;
  374. {$ENDIF}
  375. constructor TRTTIJson.Create(aSerializeLevel : TSerializeLevel; aUseEnumNames : Boolean = True);
  376. begin
  377. fSerializeLevel := aSerializeLevel;
  378. fUseEnumNames := aUseEnumNames;
  379. fUseJsonCaseSense := False;
  380. end;
  381. function TRTTIJson.DeserializeClass(aType: TClass; const aJson: TJSONObject): TObject;
  382. begin
  383. Result := nil;
  384. if (aJson = nil) or ((aJson as TJSONValue) is TJSONNull) or (aJson.Count = 0) then Exit;
  385. Result := aType.Create;
  386. try
  387. Result := DeserializeObject(Result,aJson);
  388. except
  389. on E : Exception do
  390. begin
  391. Result.Free;
  392. raise EJsonDeserializeError.CreateFmt('Deserialize error class "%s" : %s',[aType.ClassName,e.Message]);
  393. end;
  394. end;
  395. end;
  396. function TRTTIJson.DeserializeObject(aObject: TObject; const aJson: TJSONObject): TObject;
  397. var
  398. ctx: TRttiContext;
  399. rType: TRttiType;
  400. rProp: TRttiProperty;
  401. {$IFNDEF FPC}
  402. attr: TCustomAttribute;
  403. {$ENDIF}
  404. propertyname : string;
  405. begin
  406. Result := aObject;
  407. if (aJson = nil) or ((aJson as TJSONValue) is TJSONNull) or (aJson.Count = 0) or (Result = nil) then Exit;
  408. try
  409. rType := ctx.GetType(aObject.ClassInfo);
  410. for rProp in rType.GetProperties do
  411. begin
  412. {$IFNDEF FPC}
  413. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  414. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  415. {$ENDIF}
  416. begin
  417. if ((rProp.IsWritable) or (rProp.Name = 'List')) and (IsAllowedProperty(aObject,rProp.Name)) then
  418. begin
  419. propertyname := rProp.Name;
  420. {$IFNDEF FPC}
  421. for attr in rProp.GetAttributes do if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  422. if rProp.Name = 'List' then
  423. begin
  424. Result := DeserializeList(Result,propertyname,aJson);
  425. end
  426. else if (rProp.GetValue(aObject).IsObject) and (IsGenericList(rProp.GetValue(aObject).AsObject)) then
  427. begin
  428. DeserializeList(rProp.GetValue(aObject).AsObject,'List',TJSONObject(aJson.GetValue(propertyname)));
  429. end
  430. else if (not rProp.GetValue(aObject).IsObject) and (IsGenericXArray(rProp.GetValue(aObject){$IFNDEF NEXTGEN}.TypeInfo.Name{$ELSE}.TypeInfo.NameFld.ToString{$ENDIF})) then
  431. begin
  432. DeserializeXArray(Result,rProp.GetValue(aObject),rProp,propertyname,aJson);
  433. end
  434. else
  435. {$ENDIF}
  436. Result := DeserializeProperty(Result,propertyname,rProp,aJson);
  437. end;
  438. end;
  439. end;
  440. except
  441. on E : Exception do
  442. begin
  443. Result.Free;
  444. raise EJsonDeserializeError.CreateFmt('Deserialize error for object "%s" : %s',[aObject.ClassName,e.Message]);
  445. end;
  446. end;
  447. end;
  448. {$IFNDEF FPC}
  449. function TRTTIJson.DeserializeList(aObject: TObject; const aName : string; const aJson: TJSONObject) : TObject;
  450. var
  451. ctx : TRttiContext;
  452. rType : TRttiType;
  453. jarray : TJSONArray;
  454. member : TJsonValue;
  455. rvalue : TValue;
  456. i : Integer;
  457. n : Integer;
  458. rProp : TRttiProperty;
  459. {$IFNDEF DELPHIRX10_UP}
  460. rfield : TRttiField;
  461. {$ENDIF}
  462. begin
  463. Result := aObject;
  464. rType := ctx.GetType(aObject.ClassInfo);
  465. rProp := rType.GetProperty('List');
  466. if rProp = nil then Exit;
  467. //check if exists List (denotes delphi json serialized) or not (normal json serialized)
  468. member := GetJsonPairValueByName(aJson,aName);
  469. if member = nil then jArray := TJSONObject.ParseJSONValue(aJson.ToJSON) as TJSONArray
  470. else jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  471. try
  472. rvalue := DeserializeDynArray(rProp.PropertyType.Handle,Result,jArray);
  473. //i := jarray.Count;
  474. finally
  475. jArray.Free;
  476. end;
  477. if not rValue.IsEmpty then
  478. begin
  479. {$IFDEF DELPHIRX10_UP}
  480. if (TObjectList<TObject>(aObject) <> nil) and (rvalue.IsArray) then
  481. begin
  482. TObjectList<TObject>(aObject).Clear;
  483. n := rvalue.GetArrayLength - 1;
  484. for i := 0 to n do
  485. begin
  486. TObjectList<TObject>(aObject).Add(rvalue.GetArrayElement(i).AsObject);
  487. end;
  488. end;
  489. {$ELSE}
  490. n := 0;
  491. for rfield in rType.GetFields do
  492. begin
  493. if rfield.Name = 'FOwnsObjects' then rfield.SetValue(aObject,True);
  494. //if rfield.Name = 'FCount' then rfield.SetValue(aObject,i);
  495. if rfield.Name = 'FItems' then
  496. begin
  497. //if TList(aObject) <> nil then TList(aObject).Clear;
  498. //rfield.GetValue(aObject).AsObject.Free;// aValue.GetReferenceToRawData)
  499. rfield.SetValue(aObject,rValue);// .SetDynArrayProp(aObject,'fItems',Result);
  500. Break;
  501. end;
  502. end;
  503. rProp := rType.GetProperty('Count');
  504. rProp.SetValue(aObject,n);
  505. {$ENDIF}
  506. end;
  507. end;
  508. {$ENDIF}
  509. {$IFNDEF FPC}
  510. procedure TRTTIJson.DeserializeXArray(Instance : TObject; aRecord : TValue; aProperty : TRttiProperty; const aPropertyName : string; aJson : TJsonObject);
  511. var
  512. ctx : TRttiContext;
  513. rRec : TRttiRecordType;
  514. rfield : TRttiField;
  515. rValue : TValue;
  516. member : TJsonValue;
  517. jArray : TJSONArray;
  518. begin
  519. rRec := ctx.GetType(aRecord.TypeInfo).AsRecord;
  520. rfield := rRec.GetField('fArray');
  521. if rfield <> nil then
  522. begin
  523. rValue := nil;
  524. //member := TJSONPair(aJson.GetValue(rField.Name));
  525. member := GetJsonPairValueByName(aJson,aPropertyName);
  526. if (member <> nil) and (rField.FieldType.TypeKind = tkDynArray) then
  527. begin
  528. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  529. try
  530. rValue := DeserializeDynArray(rField.FieldType.Handle,nil,jArray);
  531. finally
  532. jArray.Free;
  533. end;
  534. end;
  535. end;
  536. if not rValue.IsEmpty then rField.SetValue(aRecord.GetReferenceToRawData,rValue);
  537. aProperty.SetValue(Instance,aRecord);
  538. end;
  539. {$ENDIF}
  540. function TRTTIJson.DeserializeProperty(aObject : TObject; const aName : string; aProperty : TRttiProperty; const aJson : TJSONObject) : TObject;
  541. var
  542. rValue : TValue;
  543. {$IFNDEF FPC}
  544. member : TJsonValue;
  545. {$ELSE}
  546. member : TJsonObject;
  547. {$ENDIF}
  548. objClass: TClass;
  549. jArray : TJSONArray;
  550. json : TJSONObject;
  551. begin
  552. Result := aObject;
  553. rValue := nil;
  554. {$IFNDEF FPC}
  555. //member := TJSONPair(aJson.GetValue(aName));
  556. member := GetJsonPairValueByName(aJson,aName);
  557. {$ELSE}
  558. member := TJsonObject(aJson.Find(aName));
  559. {$ENDIF}
  560. if member <> nil then
  561. begin
  562. case aProperty.PropertyType.TypeKind of
  563. tkDynArray :
  564. begin
  565. {$IFNDEF FPC}
  566. jArray := TJSONObject.ParseJSONValue(member.ToJSON) as TJSONArray;
  567. {$ELSE}
  568. jArray := TJSONArray(TJSONObject.ParseJSONValue(member.ToJSON));
  569. {$ENDIF}
  570. try
  571. {$IFNDEF FPC}
  572. aProperty.SetValue(aObject,DeserializeDynArray(aProperty.PropertyType.Handle,Result,jArray));
  573. {$ELSE}
  574. DeserializeDynArray(aProperty.PropertyType.Handle,aName,Result,jArray);
  575. {$ENDIF}
  576. Exit;
  577. finally
  578. jArray.Free;
  579. end;
  580. end;
  581. tkClass :
  582. begin
  583. //if (member.JsonValue is TJSONObject) then
  584. begin
  585. json := TJsonObject(TJSONObject.ParseJSONValue(member.ToJson));
  586. try
  587. if aProperty.GetValue(aObject).AsObject = nil then
  588. begin
  589. {$IFNDEF FPC}
  590. objClass := aProperty.PropertyType.Handle^.TypeData.ClassType;
  591. rValue := DeserializeClass(objClass,json);
  592. {$ELSE}
  593. objClass := GetObjectPropClass(aObject,aName);
  594. //objClass := GetTypeData(aProperty.PropertyType.Handle)^.ClassType;
  595. rValue := DeserializeClass(objClass,json);
  596. SetObjectProp(aObject,aName,rValue.AsObject);
  597. Exit;
  598. {$ENDIF}
  599. end
  600. else
  601. begin
  602. rValue := DeserializeObject(aProperty.GetValue(aObject).AsObject,json);
  603. Exit;
  604. end;
  605. finally
  606. json.Free;
  607. end;
  608. end
  609. end;
  610. {$IFNDEF FPC}
  611. tkRecord :
  612. begin
  613. if aProperty.GetValue(aObject).TypeInfo = System.TypeInfo(TGUID) then
  614. begin
  615. rValue:=TValue.From<TGUID>(StringToGUID(member.ToJSON.DeQuotedString('"')));
  616. end
  617. else
  618. begin
  619. json := TJSONObject.ParseJSONValue(member.ToJson) as TJSONObject;
  620. try
  621. rValue := DeserializeRecord(aProperty.GetValue(aObject),aObject,json);
  622. finally
  623. json.Free;
  624. end;
  625. end;
  626. end;
  627. {$ENDIF}
  628. else
  629. begin
  630. {$IFNDEF FPC}
  631. //avoid return unicode escaped chars if string
  632. if aProperty.PropertyType.TypeKind in [tkString, tkLString, tkWString, tkUString] then
  633. {$IFDEF DELPHIRX10_UP}
  634. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,TJsonValue(member).value)
  635. {$ELSE}
  636. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.JsonString.ToString)
  637. {$ENDIF}
  638. else rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aProperty.GetValue(aObject).TypeInfo,member.ToJSON);
  639. {$ELSE}
  640. rValue := DeserializeType(aObject,aProperty.PropertyType.TypeKind,aName,member.ToJSON);
  641. if not rValue.IsEmpty then SetPropertyValue(aObject,aName,rValue);
  642. {$ENDIF}
  643. end;
  644. end;
  645. {$IFNDEF FPC}
  646. if not rValue.IsEmpty then aProperty.SetValue(Result,rValue);
  647. {$ENDIF}
  648. end;
  649. end;
  650. {$IFNDEF FPC}
  651. function TRTTIJson.DeserializeType(aObject : TObject; aType : TTypeKind; aTypeInfo : PTypeInfo; const aValue: string) : TValue;
  652. var
  653. i : Integer;
  654. value : string;
  655. fsettings : TFormatSettings;
  656. begin
  657. try
  658. value := AnsiDequotedStr(aValue,'"');
  659. case aType of
  660. tkString, tkLString, tkWString, tkUString :
  661. begin
  662. Result := value;
  663. end;
  664. tkChar, tkWChar :
  665. begin
  666. Result := value;
  667. end;
  668. tkInteger :
  669. begin
  670. Result := StrToInt(value);
  671. end;
  672. tkInt64 :
  673. begin
  674. Result := StrToInt64(value);
  675. end;
  676. tkFloat :
  677. begin
  678. if aTypeInfo = TypeInfo(TDateTime) then
  679. begin
  680. if CompareText(value,'null') <> 0 then Result := JsonDateToDateTime(value);
  681. end
  682. else if aTypeInfo = TypeInfo(TDate) then
  683. begin
  684. if CompareText(value,'null') <> 0 then Result := StrToDate(value);
  685. end
  686. else if aTypeInfo = TypeInfo(TTime) then
  687. begin
  688. Result := StrToTime(value);
  689. end
  690. else
  691. begin
  692. fsettings := TFormatSettings.Create;
  693. Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
  694. end;
  695. end;
  696. tkEnumeration :
  697. begin
  698. if aTypeInfo = System.TypeInfo(Boolean) then
  699. begin
  700. Result := StrToBool(value);
  701. end
  702. else
  703. begin
  704. //if fUseEnumNames then TValue.Make(GetEnumValue(aTypeInfo,value),aTypeInfo, Result)
  705. // else TValue.Make(StrToInt(value),aTypeInfo, Result);
  706. if not TryStrToInt(value,i) then TValue.Make(GetEnumValue(aTypeInfo,value),aTypeInfo, Result)
  707. else TValue.Make(StrToInt(value),aTypeInfo, Result);
  708. end;
  709. end;
  710. tkSet :
  711. begin
  712. i := StringToSet(aTypeInfo,value);
  713. TValue.Make(@i,aTypeInfo,Result);
  714. end;
  715. else
  716. begin
  717. //raise EclJsonSerializerError.Create('Not supported data type!');
  718. end;
  719. end;
  720. except
  721. on E : Exception do
  722. begin
  723. raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s.%s" : %s',[aObject.ClassName,GetTypeName(aTypeInfo),e.Message]);
  724. end;
  725. end;
  726. end;
  727. {$ELSE}
  728. function TRTTIJson.DeserializeType(aObject : TObject; aType : TTypeKind; const aPropertyName, aValue: string) : TValue;
  729. var
  730. value : string;
  731. propinfo : PPropInfo;
  732. fsettings : TFormatSettings;
  733. begin
  734. try
  735. value := AnsiDequotedStr(aValue,'"');
  736. if value = '' then
  737. begin
  738. Result := nil;
  739. Exit;
  740. end;
  741. propinfo := GetPropInfo(aObject,aPropertyName);
  742. //case propinfo.PropType.Kind of
  743. case aType of
  744. tkString, tkLString, tkWString, tkUString, tkAString :
  745. begin
  746. Result := value;
  747. //SetStrProp(aObject,propinfo,value);
  748. end;
  749. tkChar, tkWChar :
  750. begin
  751. Result := value;
  752. end;
  753. tkInteger :
  754. begin
  755. Result := StrToInt(value);
  756. end;
  757. tkInt64 :
  758. begin
  759. Result := StrToInt64(value);
  760. end;
  761. tkFloat :
  762. begin
  763. if propinfo.PropType = TypeInfo(TDateTime) then
  764. begin
  765. if CompareText(value,'null') <> 0 then Result := JsonDateToDateTime(value);
  766. end
  767. else if propinfo.PropType = TypeInfo(TDate) then
  768. begin
  769. if CompareText(value,'null') <> 0 then Result := StrToDate(value);
  770. end
  771. else if propinfo.PropType = TypeInfo(TTime) then
  772. begin
  773. Result := StrToTime(value);
  774. end
  775. else
  776. begin
  777. fsettings := DefaultFormatSettings;
  778. Result := StrToFloat(StringReplace(value,'.',fsettings.DecimalSeparator,[]));
  779. end;
  780. end;
  781. tkEnumeration:
  782. begin
  783. Result := value;
  784. end;
  785. tkBool :
  786. begin
  787. Result := StrToBool(value);
  788. end;
  789. tkSet :
  790. begin
  791. Result := value;
  792. end;
  793. else
  794. begin
  795. //raise EclJsonSerializerError.Create('Not supported data type!');
  796. end;
  797. end;
  798. //if not Result.IsEmpty then SetPropertyValue(aObject,propinfo,Result);
  799. except
  800. on E : Exception do
  801. begin
  802. raise EJsonDeserializeError.CreateFmt('Deserialize error type "%s" : %s',[aObject.ClassName,e.Message]);
  803. end;
  804. end;
  805. end;
  806. {$ENDIF}
  807. function TRTTIJson.IsAllowedProperty(aObject : TObject; const aPropertyName : string) : Boolean;
  808. var
  809. propname : string;
  810. begin
  811. Result := True;
  812. propname := aPropertyName.ToLower;
  813. if IsGenericList(aObject) then
  814. begin
  815. if (propname = 'capacity') or (propname = 'count') or (propname = 'ownsobjects') then Result := False;
  816. end
  817. else if (propname = 'refcount') then Result := False;
  818. end;
  819. function TRTTIJson.IsGenericList(aObject : TObject) : Boolean;
  820. var
  821. cname : string;
  822. begin
  823. if aObject = nil then Exit(False);
  824. cname := aObject.ClassName;
  825. Result := (cname.StartsWith('TObjectList')) or (cname.StartsWith('TList'));
  826. end;
  827. function TRTTIJson.IsGenericXArray(const aClassName : string) : Boolean;
  828. begin
  829. Result := aClassName.StartsWith('TXArray');
  830. end;
  831. function TRTTIJson.GetJsonPairValueByName(aJson: TJSONObject; const aName: string): TJsonValue;
  832. var
  833. candidate : TJSONPair;
  834. i : Integer;
  835. begin
  836. if fUseJsonCaseSense then
  837. begin
  838. Result := aJson.GetValue(aName);
  839. Exit;
  840. end
  841. else
  842. begin
  843. for i := 0 to aJson.Count - 1 do
  844. begin
  845. candidate := aJson.Pairs[I];
  846. if candidate.JsonValue = nil then continue;
  847. if CompareText(candidate.JsonString{$IFNDEF FPC}.Value{$ENDIF},aName) = 0 then Exit(candidate.JsonValue);
  848. end;
  849. end;
  850. Result := nil;
  851. end;
  852. function TRTTIJson.GetJsonPairByName(aJson: TJSONObject; const aName: string): TJSONPair;
  853. var
  854. i : Integer;
  855. begin
  856. if fUseJsonCaseSense then
  857. begin
  858. Result := TJSONPair(aJson.GetValue(aName));
  859. Exit;
  860. end
  861. else
  862. begin
  863. if aJson <> nil then
  864. begin
  865. for i := 0 to aJson.Count - 1 do
  866. begin
  867. Result := aJson.Pairs[I];
  868. if Result.JsonValue = nil then continue;
  869. if CompareText(Result.JsonString{$IFNDEF FPC}.Value{$ENDIF},aName) = 0 then Exit;
  870. end;
  871. end;
  872. end;
  873. Result := nil;
  874. end;
  875. function TRTTIJson.GetPropertyValue(Instance : TObject; const PropertyName : string) : TValue;
  876. var
  877. pinfo : PPropInfo;
  878. begin
  879. Result := nil;
  880. pinfo := GetPropInfo(Instance,PropertyName);
  881. if pinfo = nil then raise EJsonSerializeError.CreateFmt('Property "%s" not found!',[PropertyName]);
  882. case pinfo.PropType^.Kind of
  883. tkInteger : Result := GetOrdProp(Instance,pinfo);
  884. tkInt64 : Result := GetInt64Prop(Instance,PropertyName);
  885. tkFloat : Result := GetFloatProp(Instance,PropertyName);
  886. tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
  887. {$IFDEF FPC}
  888. tkWString : Result := GetWideStrProp(Instance,PropertyName);
  889. tkSString,
  890. tkAString,
  891. {$ELSE}
  892. tkWString,
  893. {$ENDIF}
  894. tkLString : Result := GetStrProp(Instance,pinfo);
  895. {$IFDEF FPC}
  896. tkEnumeration :
  897. begin
  898. if fUseEnumNames then Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName))
  899. else Result := GetOrdProp(Instance,PropertyName);
  900. end;
  901. {$ELSE}
  902. tkEnumeration :
  903. begin
  904. if fUseEnumNames then Result := GetEnumName(@pinfo.PropType,GetOrdProp(Instance,PropertyName))
  905. else Result := GetOrdProp(Instance,PropertyName);
  906. end;
  907. {$ENDIF}
  908. tkSet : Result := GetSetProp(Instance,pinfo,True);
  909. {$IFNDEF FPC}
  910. tkClass :
  911. {$ELSE}
  912. tkBool : Result := Boolean(GetOrdProp(Instance,pinfo));
  913. tkObject :
  914. {$ENDIF} Result := GetObjectProp(Instance,pinfo);
  915. tkDynArray : Result := GetDynArrayProp(Instance,pinfo);
  916. end;
  917. end;
  918. function TRTTIJson.GetPropertyValueFromObject(Instance : TObject; const PropertyName : string) : TValue;
  919. var
  920. ctx : TRttiContext;
  921. rprop : TRttiProperty;
  922. begin
  923. rprop := ctx.GetType(Instance.ClassInfo).GetProperty(PropertyName);
  924. Result := rprop.GetValue(Instance);
  925. end;
  926. {$IFNDEF FPC}
  927. function TRTTIJson.GetFieldValueFromRecord(const aValue : TValue; const FieldName : string) : TValue;
  928. var
  929. ctx : TRttiContext;
  930. rec : TRttiRecordType;
  931. rfield : TRttiField;
  932. begin
  933. rec := ctx.GetType(aValue.TypeInfo).AsRecord;
  934. rfield := rec.GetField(FieldName);
  935. if rfield <> nil then Result := rField.GetValue(aValue.GetReferenceToRawData)
  936. else Result := nil;
  937. end;
  938. {$ENDIF}
  939. procedure TRTTIJson.SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue);
  940. var
  941. pinfo : PPropInfo;
  942. begin
  943. pinfo := GetPropInfo(Instance,PropertyName);
  944. SetPropertyValue(Instance,pinfo,aValue);
  945. end;
  946. procedure TRTTIJson.SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue);
  947. begin
  948. case aPropInfo.PropType^.Kind of
  949. tkInteger : SetOrdProp(Instance,aPropInfo,aValue.AsInteger);
  950. tkInt64 : SetInt64Prop(Instance,aPropInfo,aValue.AsInt64);
  951. tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
  952. tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  953. {$IFDEF FPC}
  954. tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
  955. tkSString,
  956. tkAString,
  957. {$ELSE}
  958. tkWString,
  959. {$ENDIF}
  960. tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
  961. {$IFDEF FPC}
  962. tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  963. tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
  964. {$ENDIF}
  965. tkEnumeration : SetEnumProp(Instance,aPropInfo,aValue.AsString);
  966. {$IFNDEF FPC}
  967. tkClass :
  968. {$ELSE}
  969. tkObject :
  970. {$ENDIF} SetObjectProp(Instance,aPropInfo,aValue.AsObject);
  971. end;
  972. end;
  973. {$IFDEF FPC}
  974. procedure TRTTIJson.LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  975. type
  976. TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
  977. const
  978. Delims = [' ', ',', '[', ']'];
  979. var
  980. TypeInfo: PTypeInfo;
  981. W: Cardinal;
  982. I, N: Integer;
  983. Count: Integer;
  984. EnumName: string;
  985. begin
  986. W := 0;
  987. TypeInfo := GetTypeData(GetPropType(aPropInfo))^.CompType;
  988. Count := WordCount(aValue, Delims);
  989. for N := 1 to Count do
  990. begin
  991. EnumName := ExtractWord(N, aValue, Delims);
  992. try
  993. I := GetEnumValue(TypeInfo, EnumName);
  994. if I >= 0 then Include(TCardinalSet(W),I);
  995. except
  996. end;
  997. end;
  998. SetOrdProp(aInstance,aPropInfo,W);
  999. end;
  1000. {$ENDIF}
  1001. function TRTTIJson.SerializeObject(aObject: TObject): TJSONObject;
  1002. var
  1003. ctx: TRttiContext;
  1004. {$IFNDEF FPC}
  1005. attr : TCustomAttribute;
  1006. comment : string;
  1007. {$ENDIF}
  1008. rType: TRttiType;
  1009. rProp: TRttiProperty;
  1010. jpair : TJSONPair;
  1011. ExcludeSerialize : Boolean;
  1012. propertyname : string;
  1013. propvalue : TValue;
  1014. begin
  1015. if (aObject = nil) then
  1016. begin
  1017. Result := nil;
  1018. Exit;
  1019. end;
  1020. Result := TJSONObject.Create;
  1021. try
  1022. propertyname := '';
  1023. rType := ctx.GetType(aObject.ClassInfo);
  1024. for rProp in TRTTI.GetProperties(rType,roFirstBase) do
  1025. begin
  1026. ExcludeSerialize := False;
  1027. propertyname := rProp.Name;
  1028. {$IFNDEF FPC}
  1029. comment := '';
  1030. for attr in rProp.GetAttributes do
  1031. begin
  1032. if attr is TNotSerializableProperty then ExcludeSerialize := True
  1033. else if attr is TCommentProperty then comment := TCommentProperty(attr).Comment
  1034. else if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  1035. end;
  1036. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  1037. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  1038. {$ENDIF}
  1039. begin
  1040. if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
  1041. begin
  1042. //add comment as pair
  1043. {$IFNDEF FPC}
  1044. if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
  1045. {$ENDIF}
  1046. begin
  1047. propvalue := rProp.GetValue(aObject);
  1048. jpair := TJSONPair.Create(propertyName,nil);
  1049. if (propvalue.IsObject) and (IsGenericList(propvalue.AsObject)) then
  1050. begin
  1051. jpair.JsonValue := SerializeValue(GetPropertyValueFromObject(propvalue.AsObject,'List'));
  1052. end
  1053. {$IFNDEF FPC}
  1054. else if (not propvalue.IsObject) and (IsGenericXArray(propvalue{$IFNDEF NEXTGEN}.TypeInfo.Name{$ELSE}.TypeInfo.NameFld.ToString{$ENDIF})) then
  1055. begin
  1056. jpair.JsonValue := SerializeValue(GetFieldValueFromRecord(propvalue,'fArray'));
  1057. end
  1058. {$ENDIF}
  1059. else
  1060. begin
  1061. {$IFNDEF FPC}
  1062. jpair.JsonValue := SerializeValue(propvalue);
  1063. {$ELSE}
  1064. jpair.JsonValue := SerializeValue(propvalue);// SerializeObject(aObject,rProp.PropertyType.TypeKind,propertyname);
  1065. {$ENDIF}
  1066. end;
  1067. //s := jpair.JsonValue.ToString;
  1068. if jpair.JsonValue <> nil then
  1069. begin
  1070. Result.AddPair(jpair);
  1071. end
  1072. else jpair.Free;
  1073. end;
  1074. end;
  1075. end;
  1076. end;
  1077. except
  1078. on E : Exception do
  1079. begin
  1080. Result.Free;
  1081. if not propertyname.IsEmpty then raise EJsonSerializeError.CreateFmt('Serialize Error -> Object property: "%s" (%s)',[propertyname,e.Message])
  1082. else raise EJsonSerializeError.CreateFmt('Serialize Error -> Object (%s)',[e.Message]);
  1083. end;
  1084. end;
  1085. end;
  1086. function TRTTIJson.GetValue(aAddr: Pointer; aType: TRTTIType): TValue;
  1087. begin
  1088. TValue.Make(aAddr,aType.Handle,Result);
  1089. end;
  1090. function TRTTIJson.GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue;
  1091. begin
  1092. TValue.Make(aAddr,aTypeInfo,Result);
  1093. end;
  1094. function TRTTIJson.SerializeValue(const aValue : TValue) : TJSONValue;
  1095. begin
  1096. Result := nil;
  1097. case avalue.Kind of
  1098. tkDynArray :
  1099. begin
  1100. {$IFNDEF FPC}
  1101. Result := SerializeDynArray(aValue);
  1102. {$ENDIF}
  1103. end;
  1104. tkClass :
  1105. begin
  1106. Result := TJSONValue(SerializeObject(aValue.AsObject));
  1107. end;
  1108. tkString, tkLString, tkWString, tkUString :
  1109. begin
  1110. Result := TJSONString.Create(aValue.AsString);
  1111. end;
  1112. tkChar, tkWChar :
  1113. begin
  1114. Result := TJSONString.Create(aValue.AsString);
  1115. end;
  1116. tkInteger :
  1117. begin
  1118. Result := TJSONNumber.Create(aValue.AsInteger);
  1119. end;
  1120. tkInt64 :
  1121. begin
  1122. Result := TJSONNumber.Create(aValue.AsInt64);
  1123. end;
  1124. tkFloat :
  1125. begin
  1126. if aValue.TypeInfo = TypeInfo(TDateTime) then
  1127. begin
  1128. if aValue.AsExtended <> 0.0 then Result := TJSONString.Create(DateTimeToJsonDate(aValue.AsExtended));
  1129. end
  1130. else if aValue.TypeInfo = TypeInfo(TDate) then
  1131. begin
  1132. if aValue.AsExtended <> 0.0 then Result := TJSONString.Create(DateToStr(aValue.AsExtended));
  1133. end
  1134. else if aValue.TypeInfo = TypeInfo(TTime) then
  1135. begin
  1136. Result := TJSONString.Create(TimeToStr(aValue.AsExtended));
  1137. end
  1138. else
  1139. begin
  1140. Result := TJSONNumber.Create(aValue.AsExtended);
  1141. end;
  1142. end;
  1143. tkEnumeration :
  1144. begin
  1145. if (aValue.TypeInfo = System.TypeInfo(Boolean)) then
  1146. begin
  1147. {$IF Defined(DELPHIRX10_UP) OR Defined(FPC)}
  1148. Result := TJSONBool.Create(aValue.AsBoolean);
  1149. {$ELSE}
  1150. if aValue.AsBoolean then Result := TJsonTrue.Create
  1151. else Result := TJsonFalse.Create;
  1152. {$ENDIF}
  1153. end
  1154. else
  1155. begin
  1156. //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
  1157. if fUseEnumNames then Result := TJSONString.Create(aValue.ToString)
  1158. else Result := TJSONNumber.Create(GetEnumValue(aValue.TypeInfo,aValue.ToString));
  1159. end;
  1160. end;
  1161. {$IFDEF FPC}
  1162. tkBool :
  1163. begin
  1164. Result := TJSONBool.Create(aValue.AsBoolean);
  1165. end;
  1166. {$ENDIF}
  1167. tkSet :
  1168. begin
  1169. Result := TJSONString.Create(aValue.ToString);
  1170. end;
  1171. tkRecord :
  1172. begin
  1173. {$IFNDEF FPC}
  1174. Result := SerializeRecord(aValue);
  1175. {$ENDIF}
  1176. end;
  1177. tkVariant :
  1178. begin
  1179. {$IFNDEF FPC}
  1180. case VarType(aValue.AsVariant) and VarTypeMask of
  1181. varInteger, varInt64 : Result := TJSONNumber.Create(aValue.AsInteger);
  1182. varString, varUString, varEmpty : Result := TJSONString.Create(aValue.AsString);
  1183. varDouble : Result := TJSONNumber.Create(aValue.AsExtended);
  1184. end;
  1185. {$ENDIF}
  1186. end;
  1187. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure, tkUnknown :
  1188. begin
  1189. //skip these properties
  1190. end
  1191. else
  1192. begin
  1193. {$IFNDEF FPC}
  1194. raise EJsonSerializeError.CreateFmt(cNotSupportedDataType,[GetTypeName(aValue.TypeInfo)]);
  1195. {$ELSE}
  1196. raise EJsonSerializeError.Create('Not supported Data Type');
  1197. {$ENDIF}
  1198. end;
  1199. end;
  1200. if Result = nil then Result := TJSONNull.Create;
  1201. end;
  1202. {$IFNDEF FPC}
  1203. function TRTTIJson.SerializeDynArray(const aValue: TValue) : TJsonArray;
  1204. var
  1205. ctx : TRttiContext;
  1206. rDynArray : TRTTIDynamicArrayType;
  1207. i : Integer;
  1208. jValue : TJSONValue;
  1209. element : Integer;
  1210. list : TList<TJSONValue>;
  1211. begin
  1212. element := -1;
  1213. Result := TJSONArray.Create;
  1214. try
  1215. rDynArray := ctx.GetType(aValue.TypeInfo) as TRTTIDynamicArrayType;
  1216. list := TList<TJSONValue>.Create;
  1217. list.Capacity := aValue.GetArrayLength;
  1218. for i := 0 to aValue.GetArrayLength - 1 do
  1219. begin
  1220. if not GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType).IsEmpty then
  1221. begin
  1222. element := i;
  1223. jValue := SerializeValue(GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType));
  1224. if jValue = nil then jValue := TJSONNull.Create;
  1225. list.Add(jValue);
  1226. end;
  1227. end;
  1228. Result.SetElements(list);
  1229. except
  1230. on E : Exception do
  1231. begin
  1232. if element > -1 then raise EJsonSerializeError.CreateFmt('Serialize Error -> Array[%d] (%s)',[element,e.Message])
  1233. else raise EJsonSerializeError.CreateFmt('Serialize Error -> Array (%s)',[e.Message]);
  1234. end;
  1235. end;
  1236. end;
  1237. function TRTTIJson.SerializeRecord(const aValue : TValue) : TJSONValue;
  1238. var
  1239. ctx : TRttiContext;
  1240. json : TJSONObject;
  1241. rRec : TRttiRecordType;
  1242. rField : TRttiField;
  1243. begin
  1244. rField := nil;
  1245. try
  1246. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1247. if aValue.TypeInfo = System.TypeInfo(TGUID) then
  1248. begin
  1249. Result := TJSONString.Create(GUIDToString(aValue.AsType<TGUID>));
  1250. end
  1251. else
  1252. begin
  1253. json := TJSONObject.Create;
  1254. for rField in rRec.GetFields do
  1255. begin
  1256. json.AddPair(rField.Name,SerializeValue(rField.GetValue(aValue.GetReferenceToRawData)));
  1257. end;
  1258. Result := json;
  1259. end;
  1260. except
  1261. on E : Exception do
  1262. begin
  1263. if rField <> nil then raise EJsonSerializeError.CreateFmt('Serialize Error -> Record property "%s" (%s)',[rField.Name,e.Message])
  1264. else raise EJsonSerializeError.CreateFmt('Serialize Error -> Record (%s)',[e.Message]);
  1265. end;
  1266. end;
  1267. end;
  1268. {$ELSE}
  1269. function TRTTIJson.GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  1270. begin
  1271. Result := aPropInfo^.PropType;
  1272. end;
  1273. function TRTTIJson.FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  1274. const
  1275. Precisions: array[TFloatType] of Integer = (7, 15, 18, 18, 19);
  1276. var
  1277. fsettings : TFormatSettings;
  1278. begin
  1279. fsettings := FormatSettings;
  1280. Result := StringReplace(FloatToStrF(GetFloatProp(aObject, aPropInfo), ffGeneral,
  1281. Precisions[GetTypeData(GetPropType(aPropInfo))^.FloatType],0),
  1282. '.',fsettings.DecimalSeparator,[rfReplaceAll]);
  1283. end;
  1284. function TRTTIJson.SerializeObject(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  1285. var
  1286. propinfo : PPropInfo;
  1287. jArray : TJsonArray;
  1288. jPair : TJsonPair;
  1289. jValue : TJsonValue;
  1290. i : Integer;
  1291. pArr : Pointer;
  1292. rValue : TValue;
  1293. rItemValue : TValue;
  1294. len : Integer;
  1295. begin
  1296. try
  1297. Result := TJSONPair.Create(aPropertyName,nil);
  1298. propinfo := GetPropInfo(aObject,aPropertyName);
  1299. //case propinfo.PropType.Kind of
  1300. case aType of
  1301. tkDynArray :
  1302. begin
  1303. len := 0;
  1304. jArray := TJSONArray.Create;
  1305. try
  1306. pArr := GetDynArrayProp(aObject,aPropertyName);
  1307. TValue.Make(@pArr,propinfo.PropType, rValue);
  1308. if rValue.IsArray then
  1309. begin
  1310. len := rValue.GetArrayLength;
  1311. for i := 0 to len - 1 do
  1312. begin
  1313. rItemValue := rValue.GetArrayElement(i);
  1314. jValue := SerializeValue(rItemValue);
  1315. jArray.Add(jValue);
  1316. end;
  1317. end;
  1318. Result.JsonValue := jArray;
  1319. finally
  1320. //DynArrayClear(pArr,propinfo.PropType);
  1321. pArr := nil;
  1322. end;
  1323. end;
  1324. tkClass :
  1325. begin
  1326. Result.JsonValue := TJSONValue(SerializeObject(GetObjectProp(aObject,aPropertyName)));
  1327. end;
  1328. tkString, tkLString, tkWString, tkUString, tkAString :
  1329. begin
  1330. Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
  1331. end;
  1332. tkChar, tkWChar :
  1333. begin
  1334. Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
  1335. end;
  1336. tkInteger :
  1337. begin
  1338. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1339. end;
  1340. tkInt64 :
  1341. begin
  1342. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1343. end;
  1344. tkFloat :
  1345. begin
  1346. if propinfo.PropType = TypeInfo(TDateTime) then
  1347. begin
  1348. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
  1349. end
  1350. else if propinfo.PropType = TypeInfo(TDate) then
  1351. begin
  1352. Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
  1353. end
  1354. else if propinfo.PropType = TypeInfo(TTime) then
  1355. begin
  1356. Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
  1357. end
  1358. else
  1359. begin
  1360. //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
  1361. Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
  1362. end;
  1363. end;
  1364. tkEnumeration,tkBool :
  1365. begin
  1366. if (propinfo.PropType = System.TypeInfo(Boolean)) then
  1367. begin
  1368. Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
  1369. end
  1370. else
  1371. begin
  1372. if fUseEnumNames then Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)))
  1373. else Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1374. //Result.JsonValue := TJSONString.Create(aValue.ToString);
  1375. end;
  1376. end;
  1377. tkSet :
  1378. begin
  1379. Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
  1380. end;
  1381. {$IFNDEF FPC}
  1382. tkRecord :
  1383. begin
  1384. Result.JsonValue := SerializeRecord(aValue);
  1385. end;
  1386. {$ENDIF}
  1387. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1388. begin
  1389. //skip these properties
  1390. //FreeAndNil(Result);
  1391. end
  1392. else
  1393. begin
  1394. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1395. end;
  1396. end;
  1397. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1398. except
  1399. on E : Exception do
  1400. begin
  1401. Result.Free;
  1402. {$IFNDEF FPC}
  1403. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1404. {$ENDIF}
  1405. end;
  1406. end;
  1407. end;
  1408. {$ENDIF}
  1409. { TJsonSerializer}
  1410. constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel; aUseEnumNames : Boolean = True);
  1411. begin
  1412. {$IFDEF FPC}
  1413. if aSerializeLevel = TSerializeLevel.slPublicProperty then raise EJsonSerializeError.Create('FreePascal RTTI only supports published properties');
  1414. {$ENDIF}
  1415. fSerializeLevel := aSerializeLevel;
  1416. fUseEnumNames := aUseEnumNames;
  1417. fUseJsonCaseSense := False;
  1418. fRTTIJson := TRTTIJson.Create(aSerializeLevel,aUseEnumNames);
  1419. fRTTIJson.UseJsonCaseSense := fUseJsonCaseSense;
  1420. end;
  1421. destructor TJsonSerializer.Destroy;
  1422. begin
  1423. fRTTIJson.Free;
  1424. inherited;
  1425. end;
  1426. function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObject;
  1427. var
  1428. json: TJSONObject;
  1429. begin
  1430. try
  1431. {$IFDEF DELPHIRX10_UP}
  1432. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1433. {$ELSE}
  1434. {$IFDEF FPC}
  1435. json := TJSONObject(TJSONObject.ParseJSONValue(aJson,True));
  1436. {$ELSE}
  1437. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1438. {$ENDIF}
  1439. {$ENDIF}
  1440. except
  1441. raise EJsonDeserializeError.Create(cNotValidJson);
  1442. end;
  1443. try
  1444. Result := fRTTIJson.DeserializeClass(aType,json);
  1445. finally
  1446. json.Free;
  1447. end;
  1448. end;
  1449. function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TObject;
  1450. var
  1451. json: TJSONObject;
  1452. begin;
  1453. try
  1454. {$IFDEF DELPHIRX10_UP}
  1455. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1456. {$ELSE}
  1457. {$IFDEF FPC}
  1458. json := TJSONObject(TJSONObject.ParseJSONValue(aJson,True));
  1459. {$ELSE}
  1460. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1461. {$ENDIF}
  1462. {$ENDIF}
  1463. except
  1464. raise EJsonDeserializeError.Create(cNotValidJson);
  1465. end;
  1466. try
  1467. Result := fRTTIJson.DeserializeObject(aObject,json);
  1468. finally
  1469. json.Free;
  1470. end;
  1471. end;
  1472. function TJsonSerializer.ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  1473. var
  1474. json: TJSONObject;
  1475. begin
  1476. json := fRTTIJson.SerializeObject(aObject);
  1477. try
  1478. if aIndent then Result := TJsonUtils.JsonFormat(json.ToJSON)
  1479. else Result := json.ToJSON;
  1480. finally
  1481. json.Free;
  1482. end;
  1483. end;
  1484. function TJsonSerializer.ObjectToJsonString(aObject : TObject; aIndent : Boolean = False): string;
  1485. var
  1486. json: TJSONObject;
  1487. begin
  1488. json := fRTTIJson.SerializeObject(aObject);
  1489. try
  1490. if aIndent then Result := TJsonUtils.JsonFormat(json.ToString)
  1491. else Result := json.ToString;
  1492. finally
  1493. json.Free;
  1494. end;
  1495. end;
  1496. function TJsonSerializer.ValueToJson(const aValue: TValue; aIndent: Boolean): string;
  1497. var
  1498. json: TJSONValue;
  1499. begin
  1500. json:= fRTTIJson.SerializeValue(aValue);
  1501. if json = nil then raise EJsonSerializerError.Create('Error serializing TValue');
  1502. try
  1503. if aIndent then Result := TJsonUtils.JsonFormat(json{$IFNDEF FPC}.ToJSON{$ELSE}.AsJson{$ENDIF})
  1504. else Result := json{$IFNDEF FPC}.ToJSON{$ELSE}.AsJson{$ENDIF};
  1505. finally
  1506. json.Free;
  1507. end;
  1508. end;
  1509. function TJsonSerializer.ValueToJsonString(const aValue: TValue; aIndent: Boolean): string;
  1510. var
  1511. json: TJSONValue;
  1512. begin
  1513. json:= fRTTIJson.SerializeValue(aValue);
  1514. if json = nil then raise EJsonSerializerError.Create('Error serializing TValue');
  1515. try
  1516. if aIndent then Result := TJsonUtils.JsonFormat(json.ToString)
  1517. else Result := json.ToString;
  1518. finally
  1519. json.Free;
  1520. end;
  1521. end;
  1522. function TJsonSerializer.ArrayToJson<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1523. var
  1524. json: TJSONValue;
  1525. begin
  1526. json:= fRTTIJson.SerializeValue(TValue.From<TArray<T>>(aArray));
  1527. if json = nil then raise EJsonSerializerError.Create('Error serializing Array');
  1528. try
  1529. if aIndent then Result := TJsonUtils.JsonFormat(json{$IFNDEF FPC}.ToJSON{$ELSE}.AsJson{$ENDIF})
  1530. else Result := json{$IFNDEF FPC}.ToJSON{$ELSE}.AsJson{$ENDIF};
  1531. finally
  1532. json.Free;
  1533. end;
  1534. end;
  1535. function TJsonSerializer.ArrayToJsonString<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1536. var
  1537. json: TJSONValue;
  1538. begin
  1539. json:= fRTTIJson.SerializeValue(TValue.From<TArray<T>>(aArray));
  1540. if json = nil then raise EJsonSerializerError.Create('Error serializing Array');
  1541. try
  1542. if aIndent then Result := TJsonUtils.JsonFormat(json.ToString)
  1543. else Result := json.ToString;
  1544. finally
  1545. json.Free;
  1546. end;
  1547. end;
  1548. {$IFNDEF FPC}
  1549. function TJsonSerializer.JsonToArray<T>(const aJson: string): TArray<T>;
  1550. var
  1551. jarray: TJSONArray;
  1552. value : TValue;
  1553. begin;
  1554. try
  1555. {$If Defined(FPC) OR Defined(DELPHIRX10_UP)}
  1556. jarray := TJSONObject.ParseJSONValue(aJson,True) as TJSONArray;
  1557. {$ELSE}
  1558. jarray := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONArray;
  1559. {$ENDIF}
  1560. except
  1561. raise EJsonDeserializeError.Create(cNotValidJson);
  1562. end;
  1563. try
  1564. value := fRTTIJson.DeserializeDynArray(PTypeInfo(TypeInfo(TArray<T>)),nil,jarray);
  1565. Result := value.AsType<TArray<T>>;
  1566. finally
  1567. jarray.Free;
  1568. end;
  1569. end;
  1570. function TJsonSerializer.JsonToValue(const aJson: string): TValue;
  1571. var
  1572. json: TJSONObject;
  1573. value : TValue;
  1574. begin;
  1575. try
  1576. {$If Defined(FPC) OR Defined(DELPHIRX10_UP)}
  1577. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1578. {$ELSE}
  1579. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1580. {$ENDIF}
  1581. except
  1582. raise EJsonDeserializeError.Create(cNotValidJson);
  1583. end;
  1584. try
  1585. value := fRTTIJson.DeserializeRecord(value,nil,json);
  1586. Result := value; // value.AsType<TArray<T>>;
  1587. finally
  1588. json.Free;
  1589. end;
  1590. end;
  1591. {$ENDIF}
  1592. procedure TJsonSerializer.SetUseEnumNames(const Value: Boolean);
  1593. begin
  1594. fUseEnumNames := Value;
  1595. if Assigned(fRTTIJson) then fRTTIJson.UseEnumNames := Value;
  1596. end;
  1597. procedure TJsonSerializer.SetUseJsonCaseSense(const Value: Boolean);
  1598. begin
  1599. fUseJsonCaseSense := Value;
  1600. if Assigned(fRTTIJson) then fRTTIJson.UseJsonCaseSense := Value;
  1601. end;
  1602. {$IFNDEF FPC}
  1603. { TCommentProperty }
  1604. constructor TCommentProperty.Create(const aComment: string);
  1605. begin
  1606. fComment := aComment;
  1607. end;
  1608. { TCustomNameProperty }
  1609. constructor TCustomNameProperty.Create(const aName: string);
  1610. begin
  1611. fName := aName;
  1612. end;
  1613. {$ENDIF}
  1614. end.