Quick.Json.Serializer.pas 60 KB

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