Quick.Json.Serializer.pas 57 KB

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