Quick.Json.Serializer.pas 57 KB

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