Quick.Json.Serializer.pas 55 KB

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