Quick.Json.Serializer.pas 57 KB

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