Quick.Json.Serializer.pas 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814
  1. { ***************************************************************************
  2. Copyright (c) 2015-2020 Kike Pérez
  3. Unit : Quick.JSON.Serializer
  4. Description : Json Serializer
  5. Author : Kike Pérez
  6. Version : 1.11
  7. Created : 21/05/2018
  8. Modified : 12/03/2020
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Json.Serializer;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. Rtti,
  28. TypInfo,
  29. {$IFDEF FPC}
  30. rttiutils,
  31. fpjson,
  32. jsonparser,
  33. strUtils,
  34. //jsonreader,
  35. //fpjsonrtti,
  36. Quick.Json.fpc.Compatibility,
  37. {$ELSE}
  38. {$IFDEF DELPHIXE7_UP}
  39. System.Json,
  40. {$ENDIF}
  41. {$IFDEF DELPHIRX10_UP}
  42. 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. if pinfo = nil then raise EJsonSerializeError.CreateFmt('Property "%s" not found!',[PropertyName]);
  886. case pinfo.PropType^.Kind of
  887. tkInteger : Result := GetOrdProp(Instance,pinfo);
  888. tkInt64 : Result := GetInt64Prop(Instance,PropertyName);
  889. tkFloat : Result := GetFloatProp(Instance,PropertyName);
  890. tkChar : Result := Char(GetOrdProp(Instance,PropertyName));
  891. {$IFDEF FPC}
  892. tkWString : Result := GetWideStrProp(Instance,PropertyName);
  893. tkSString,
  894. tkAString,
  895. {$ELSE}
  896. tkWString,
  897. {$ENDIF}
  898. tkLString : Result := GetStrProp(Instance,pinfo);
  899. {$IFDEF FPC}
  900. tkEnumeration :
  901. begin
  902. if fUseEnumNames then Result := GetEnumName(pinfo.PropType,GetOrdProp(Instance,PropertyName))
  903. else Result := GetOrdProp(Instance,PropertyName);
  904. end;
  905. {$ELSE}
  906. tkEnumeration :
  907. begin
  908. if fUseEnumNames then Result := GetEnumName(@pinfo.PropType,GetOrdProp(Instance,PropertyName))
  909. else Result := GetOrdProp(Instance,PropertyName);
  910. end;
  911. {$ENDIF}
  912. tkSet : Result := GetSetProp(Instance,pinfo,True);
  913. {$IFNDEF FPC}
  914. tkClass :
  915. {$ELSE}
  916. tkBool : Result := Boolean(GetOrdProp(Instance,pinfo));
  917. tkObject :
  918. {$ENDIF} Result := GetObjectProp(Instance,pinfo);
  919. tkDynArray : Result := GetDynArrayProp(Instance,pinfo);
  920. end;
  921. end;
  922. function TRTTIJson.GetPropertyValueFromObject(Instance : TObject; const PropertyName : string) : TValue;
  923. var
  924. ctx : TRttiContext;
  925. rprop : TRttiProperty;
  926. begin
  927. rprop := ctx.GetType(Instance.ClassInfo).GetProperty(PropertyName);
  928. Result := rprop.GetValue(Instance);
  929. end;
  930. {$IFNDEF FPC}
  931. function TRTTIJson.GetFieldValueFromRecord(aValue : TValue; const FieldName : string) : TValue;
  932. var
  933. ctx : TRttiContext;
  934. rec : TRttiRecordType;
  935. rfield : TRttiField;
  936. begin
  937. rec := ctx.GetType(aValue.TypeInfo).AsRecord;
  938. rfield := rec.GetField(FieldName);
  939. if rfield <> nil then Result := rField.GetValue(aValue.GetReferenceToRawData)
  940. else Result := nil;
  941. end;
  942. {$ENDIF}
  943. procedure TRTTIJson.SetPropertyValue(Instance : TObject; const PropertyName : string; aValue : TValue);
  944. var
  945. pinfo : PPropInfo;
  946. begin
  947. pinfo := GetPropInfo(Instance,PropertyName);
  948. SetPropertyValue(Instance,pinfo,aValue);
  949. end;
  950. procedure TRTTIJson.SetPropertyValue(Instance : TObject; aPropInfo : PPropInfo; aValue : TValue);
  951. begin
  952. case aPropInfo.PropType^.Kind of
  953. tkInteger : SetOrdProp(Instance,aPropInfo,aValue.AsInteger);
  954. tkInt64 : SetInt64Prop(Instance,aPropInfo,aValue.AsInt64);
  955. tkFloat : SetFloatProp(Instance,aPropInfo,aValue.AsExtended);
  956. tkChar : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  957. {$IFDEF FPC}
  958. tkWString : SetWideStrProp(Instance,aPropInfo,aValue.AsString);
  959. tkSString,
  960. tkAString,
  961. {$ELSE}
  962. tkWString,
  963. {$ENDIF}
  964. tkLString : SetStrProp(Instance,aPropInfo,aValue.AsString);
  965. {$IFDEF FPC}
  966. tkBool : SetOrdProp(Instance,aPropInfo,aValue.AsOrdinal);
  967. tkSet : LoadSetProperty(Instance,aPropInfo,aValue.AsString);
  968. {$ENDIF}
  969. tkEnumeration : SetEnumProp(Instance,aPropInfo,aValue.AsString);
  970. {$IFNDEF FPC}
  971. tkClass :
  972. {$ELSE}
  973. tkObject :
  974. {$ENDIF} SetObjectProp(Instance,aPropInfo,aValue.AsObject);
  975. end;
  976. end;
  977. {$IFDEF FPC}
  978. procedure TRTTIJson.LoadSetProperty(aInstance : TObject; aPropInfo: PPropInfo; const aValue: string);
  979. type
  980. TCardinalSet = set of 0..SizeOf(Cardinal) * 8 - 1;
  981. const
  982. Delims = [' ', ',', '[', ']'];
  983. var
  984. TypeInfo: PTypeInfo;
  985. W: Cardinal;
  986. I, N: Integer;
  987. Count: Integer;
  988. EnumName: string;
  989. begin
  990. W := 0;
  991. TypeInfo := GetTypeData(GetPropType(aPropInfo))^.CompType;
  992. Count := WordCount(aValue, Delims);
  993. for N := 1 to Count do
  994. begin
  995. EnumName := ExtractWord(N, aValue, Delims);
  996. try
  997. I := GetEnumValue(TypeInfo, EnumName);
  998. if I >= 0 then Include(TCardinalSet(W),I);
  999. except
  1000. end;
  1001. end;
  1002. SetOrdProp(aInstance,aPropInfo,W);
  1003. end;
  1004. {$ENDIF}
  1005. function TRTTIJson.Serialize(aObject: TObject): TJSONObject;
  1006. var
  1007. ctx: TRttiContext;
  1008. {$IFNDEF FPC}
  1009. attr : TCustomAttribute;
  1010. comment : string;
  1011. {$ENDIF}
  1012. rType: TRttiType;
  1013. rProp: TRttiProperty;
  1014. jpair : TJSONPair;
  1015. ExcludeSerialize : Boolean;
  1016. propertyname : string;
  1017. propvalue : TValue;
  1018. begin
  1019. if (aObject = nil) then
  1020. begin
  1021. Result := nil;
  1022. Exit;
  1023. end;
  1024. Result := TJSONObject.Create;
  1025. try
  1026. rType := ctx.GetType(aObject.ClassInfo);
  1027. try
  1028. //s := rType.ToString;
  1029. for rProp in rType.GetProperties do
  1030. begin
  1031. ExcludeSerialize := False;
  1032. propertyname := rProp.Name;
  1033. {$IFNDEF FPC}
  1034. comment := '';
  1035. for attr in rProp.GetAttributes do
  1036. begin
  1037. if attr is TNotSerializableProperty then ExcludeSerialize := True
  1038. else if attr is TCommentProperty then comment := TCommentProperty(attr).Comment
  1039. else if attr is TCustomNameProperty then propertyname := TCustomNameProperty(attr).Name;
  1040. end;
  1041. if ((fSerializeLevel = slPublicProperty) and (rProp.PropertyType.IsPublicType))
  1042. or ((fSerializeLevel = slPublishedProperty) and ((IsPublishedProp(aObject,rProp.Name)) or (rProp.Name = 'List'))) then
  1043. {$ENDIF}
  1044. begin
  1045. if (IsAllowedProperty(aObject,propertyname)) and (not ExcludeSerialize) then
  1046. begin
  1047. //add comment as pair
  1048. {$IFNDEF FPC}
  1049. if comment <> '' then Result.AddPair(TJSONPair.Create('#Comment#->'+propertyname,Comment));
  1050. {$ENDIF}
  1051. begin
  1052. propvalue := rProp.GetValue(aObject);
  1053. if (propvalue.IsObject) and (IsGenericList(propvalue.AsObject)) then
  1054. begin
  1055. jpair := Serialize(propertyname,GetPropertyValueFromObject(propvalue.AsObject,'List'));
  1056. end
  1057. {$IFNDEF FPC}
  1058. else if (not propvalue.IsObject) and (IsGenericXArray(propvalue{$IFNDEF NEXTGEN}.TypeInfo.Name{$ELSE}.TypeInfo.NameFld.ToString{$ENDIF})) then
  1059. begin
  1060. jpair := Serialize(propertyname,GetFieldValueFromRecord(propvalue,'fArray'));
  1061. end
  1062. {$ENDIF}
  1063. else
  1064. begin
  1065. {$IFNDEF FPC}
  1066. jpair := Serialize(propertyname,propvalue);
  1067. {$ELSE}
  1068. jpair := Serialize(aObject,rProp.PropertyType.TypeKind,propertyname);
  1069. {$ENDIF}
  1070. end;
  1071. //s := jpair.JsonValue.ToString;
  1072. if jpair <> nil then
  1073. begin
  1074. Result.AddPair(jpair);
  1075. end
  1076. else jpair.Free;
  1077. end;
  1078. //Result.AddPair(Serialize(rProp.Name,rProp.GetValue(aObject)));
  1079. //s := Result.ToJSON;
  1080. end;
  1081. end;
  1082. end;
  1083. finally
  1084. ctx.Free;
  1085. end;
  1086. except
  1087. on E : Exception do
  1088. begin
  1089. Result.Free;
  1090. raise EJsonSerializeError.CreateFmt('Serialize error object "%s" : %s',[aObject.ClassName,e.Message]);
  1091. end;
  1092. end;
  1093. end;
  1094. function TRTTIJson.GetValue(aAddr: Pointer; aType: TRTTIType): TValue;
  1095. begin
  1096. TValue.Make(aAddr,aType.Handle,Result);
  1097. end;
  1098. function TRTTIJson.GetValue(aAddr: Pointer; aTypeInfo: PTypeInfo): TValue;
  1099. begin
  1100. TValue.Make(aAddr,aTypeInfo,Result);
  1101. end;
  1102. {$IFNDEF FPC}
  1103. function TRTTIJson.Serialize(const aName : string; aValue : TValue) : TJSONPair;
  1104. var
  1105. ctx: TRttiContext;
  1106. rRec : TRttiRecordType;
  1107. rField : TRttiField;
  1108. rDynArray : TRTTIDynamicArrayType;
  1109. json : TJSONObject;
  1110. jArray : TJSONArray;
  1111. jPair : TJSONPair;
  1112. jValue : TJSONValue;
  1113. i : Integer;
  1114. begin
  1115. Result := TJSONPair.Create(aName,nil);
  1116. //Result.JsonString := TJSONString(aName);
  1117. try
  1118. case avalue.Kind of
  1119. tkDynArray :
  1120. begin
  1121. jArray := TJSONArray.Create;
  1122. rDynArray := ctx.GetType(aValue.TypeInfo) as TRTTIDynamicArrayType;
  1123. try
  1124. for i := 0 to aValue.GetArrayLength - 1 do
  1125. begin
  1126. if not GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType).IsEmpty then
  1127. begin
  1128. jValue := nil;
  1129. jPair := Serialize(aName,GetValue(PPByte(aValue.GetReferenceToRawData)^ + rDynArray.ElementType.TypeSize * i, rDynArray.ElementType));
  1130. try
  1131. //jValue := TJsonValue(jPair.JsonValue.Clone);
  1132. jValue := jPair.JsonValue;
  1133. if jValue <> nil then
  1134. begin
  1135. jArray.AddElement(jValue);
  1136. jPair.JsonValue.Owned := False;
  1137. end;
  1138. finally
  1139. jPair.Free;
  1140. if jValue <> nil then jValue.Owned := True;
  1141. end;
  1142. end;
  1143. end;
  1144. Result.JsonValue := jArray;
  1145. finally
  1146. ctx.Free;
  1147. end;
  1148. end;
  1149. tkClass :
  1150. begin
  1151. Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
  1152. end;
  1153. tkString, tkLString, tkWString, tkUString :
  1154. begin
  1155. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1156. end;
  1157. tkChar, tkWChar :
  1158. begin
  1159. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1160. end;
  1161. tkInteger :
  1162. begin
  1163. Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  1164. end;
  1165. tkInt64 :
  1166. begin
  1167. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  1168. end;
  1169. tkFloat :
  1170. begin
  1171. if aValue.TypeInfo = TypeInfo(TDateTime) then
  1172. begin
  1173. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(aValue.AsExtended));
  1174. end
  1175. else if aValue.TypeInfo = TypeInfo(TDate) then
  1176. begin
  1177. Result.JsonValue := TJSONString.Create(DateToStr(aValue.AsExtended));
  1178. end
  1179. else if aValue.TypeInfo = TypeInfo(TTime) then
  1180. begin
  1181. Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
  1182. end
  1183. else
  1184. begin
  1185. Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  1186. end;
  1187. end;
  1188. tkEnumeration :
  1189. begin
  1190. if (aValue.TypeInfo = System.TypeInfo(Boolean)) then
  1191. begin
  1192. {$IFDEF DELPHIRX10_UP}
  1193. Result.JsonValue := TJSONBool.Create(aValue.AsBoolean);
  1194. {$ELSE}
  1195. if aValue.AsBoolean then Result.JsonValue := TJsonTrue.Create
  1196. else Result.JsonValue := TJsonFalse.Create;
  1197. {$ENDIF}
  1198. end
  1199. else
  1200. begin
  1201. //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
  1202. if fUseEnumNames then Result.JsonValue := TJSONString.Create(aValue.ToString)
  1203. else Result.JsonValue := TJSONNumber.Create(GetEnumValue(aValue.TypeInfo,aValue.ToString));
  1204. end;
  1205. end;
  1206. tkSet :
  1207. begin
  1208. Result.JsonValue := TJSONString.Create(aValue.ToString);
  1209. end;
  1210. tkRecord :
  1211. begin
  1212. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1213. try
  1214. json := TJSONObject.Create;
  1215. for rField in rRec.GetFields do
  1216. begin
  1217. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1218. end;
  1219. Result.JsonValue := json;
  1220. finally
  1221. ctx.Free;
  1222. end;
  1223. end;
  1224. tkVariant :
  1225. begin
  1226. case VarType(aValue.AsVariant) and VarTypeMask of
  1227. varInteger, varInt64 : Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  1228. varString, varUString, varEmpty : Result.JsonValue := TJSONString.Create(aValue.AsString);
  1229. varDouble : Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  1230. end;
  1231. end;
  1232. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1233. begin
  1234. //skip these properties
  1235. //FreeAndNil(Result);
  1236. end
  1237. else
  1238. begin
  1239. raise EJsonSerializeError.CreateFmt(cNotSupportedDataType,[aName,GetTypeName(aValue.TypeInfo)]);
  1240. end;
  1241. end;
  1242. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1243. except
  1244. on E : Exception do
  1245. begin
  1246. Result.Free;
  1247. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1248. end;
  1249. end;
  1250. end;
  1251. {$ELSE}
  1252. function TRTTIJson.GetPropType(aPropInfo: PPropInfo): PTypeInfo;
  1253. begin
  1254. Result := aPropInfo^.PropType;
  1255. end;
  1256. function TRTTIJson.FloatProperty(aObject : TObject; aPropInfo: PPropInfo): string;
  1257. const
  1258. Precisions: array[TFloatType] of Integer = (7, 15, 18, 18, 19);
  1259. var
  1260. fsettings : TFormatSettings;
  1261. begin
  1262. fsettings := FormatSettings;
  1263. Result := StringReplace(FloatToStrF(GetFloatProp(aObject, aPropInfo), ffGeneral,
  1264. Precisions[GetTypeData(GetPropType(aPropInfo))^.FloatType],0),
  1265. '.',fsettings.DecimalSeparator,[rfReplaceAll]);
  1266. end;
  1267. function TRTTIJson.Serialize(const aName : string; aValue : TValue) : TJSONPair;
  1268. begin
  1269. Result := TJSONPair.Create(aName,nil);
  1270. //Result.JsonString := TJSONString(aName);
  1271. try
  1272. case avalue.Kind of
  1273. tkClass :
  1274. begin
  1275. Result.JsonValue := TJSONValue(Serialize(aValue.AsObject));
  1276. end;
  1277. tkString, tkLString, tkWString, tkUString :
  1278. begin
  1279. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1280. end;
  1281. tkChar, tkWChar :
  1282. begin
  1283. Result.JsonValue := TJSONString.Create(aValue.AsString);
  1284. end;
  1285. tkInteger :
  1286. begin
  1287. Result.JsonValue := TJSONNumber.Create(aValue.AsInteger);
  1288. end;
  1289. tkInt64 :
  1290. begin
  1291. Result.JsonValue := TJSONNumber.Create(aValue.AsInt64);
  1292. end;
  1293. tkFloat :
  1294. begin
  1295. if aValue.TypeInfo = TypeInfo(TDateTime) then
  1296. begin
  1297. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(aValue.AsExtended));
  1298. end
  1299. else if aValue.TypeInfo = TypeInfo(TDate) then
  1300. begin
  1301. Result.JsonValue := TJSONString.Create(DateToStr(aValue.AsExtended));
  1302. end
  1303. else if aValue.TypeInfo = TypeInfo(TTime) then
  1304. begin
  1305. Result.JsonValue := TJSONString.Create(TimeToStr(aValue.AsExtended));
  1306. end
  1307. else
  1308. begin
  1309. Result.JsonValue := TJSONNumber.Create(aValue.AsExtended);
  1310. end;
  1311. end;
  1312. tkEnumeration :
  1313. begin
  1314. if (aValue.TypeInfo = System.TypeInfo(Boolean)) then
  1315. begin
  1316. Result.JsonValue := TJSONBool.Create(aValue.AsBoolean);
  1317. end
  1318. else
  1319. begin
  1320. //Result.JsonValue := TJSONString.Create(GetEnumName(aValue.TypeInfo,aValue.AsOrdinal));
  1321. if fUseEnumNames then Result.JsonValue := TJSONString.Create(aValue.ToString)
  1322. else Result.JsonValue := TJSONNumber.Create(GetEnumValue(aValue.TypeInfo,aValue.ToString));
  1323. end;
  1324. end;
  1325. tkSet :
  1326. begin
  1327. Result.JsonValue := TJSONString.Create(aValue.ToString);
  1328. end;
  1329. else
  1330. begin
  1331. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1332. end;
  1333. end;
  1334. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1335. except
  1336. Result.Free;
  1337. end;
  1338. end;
  1339. function TRTTIJson.Serialize(aObject : TObject; aType : TTypeKind; const aPropertyName : string) : TJSONPair;
  1340. var
  1341. propinfo : PPropInfo;
  1342. jArray : TJsonArray;
  1343. jPair : TJsonPair;
  1344. jValue : TJsonValue;
  1345. i : Integer;
  1346. pArr : Pointer;
  1347. rValue : TValue;
  1348. rItemValue : TValue;
  1349. len : Integer;
  1350. begin
  1351. try
  1352. Result := TJSONPair.Create(aPropertyName,nil);
  1353. propinfo := GetPropInfo(aObject,aPropertyName);
  1354. //case propinfo.PropType.Kind of
  1355. case aType of
  1356. tkDynArray :
  1357. begin
  1358. len := 0;
  1359. jArray := TJSONArray.Create;
  1360. try
  1361. pArr := GetDynArrayProp(aObject,aPropertyName);
  1362. TValue.Make(@pArr,propinfo.PropType, rValue);
  1363. if rValue.IsArray then
  1364. begin
  1365. len := rValue.GetArrayLength;
  1366. for i := 0 to len - 1 do
  1367. begin
  1368. rItemValue := rValue.GetArrayElement(i);
  1369. jPair := Serialize(aPropertyName,rItemValue);
  1370. try
  1371. //jValue := TJsonValue(jPair.JsonValue.Clone);
  1372. jValue := jPair.JsonValue;
  1373. jArray.Add(jValue);
  1374. //jPair.JsonValue.Owned := False;
  1375. finally
  1376. jPair.Free;
  1377. //jValue.Owned := True;
  1378. end;
  1379. end;
  1380. end;
  1381. Result.JsonValue := jArray;
  1382. finally
  1383. //DynArrayClear(pArr,propinfo.PropType);
  1384. pArr := nil;
  1385. end;
  1386. end;
  1387. tkClass :
  1388. begin
  1389. Result.JsonValue := TJSONValue(Serialize(GetObjectProp(aObject,aPropertyName)));
  1390. end;
  1391. tkString, tkLString, tkWString, tkUString, tkAString :
  1392. begin
  1393. Result.JsonValue := TJSONString.Create(GetStrProp(aObject,aPropertyName));
  1394. end;
  1395. tkChar, tkWChar :
  1396. begin
  1397. Result.JsonValue := TJSONString.Create(Char(GetOrdProp(aObject,aPropertyName)));
  1398. end;
  1399. tkInteger :
  1400. begin
  1401. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1402. end;
  1403. tkInt64 :
  1404. begin
  1405. Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1406. end;
  1407. tkFloat :
  1408. begin
  1409. if propinfo.PropType = TypeInfo(TDateTime) then
  1410. begin
  1411. Result.JsonValue := TJSONString.Create(DateTimeToJsonDate(GetFloatProp(aObject,aPropertyName)));
  1412. end
  1413. else if propinfo.PropType = TypeInfo(TDate) then
  1414. begin
  1415. Result.JsonValue := TJSONString.Create(DateToStr(GetFloatProp(aObject,aPropertyName)));
  1416. end
  1417. else if propinfo.PropType = TypeInfo(TTime) then
  1418. begin
  1419. Result.JsonValue := TJSONString.Create(TimeToStr(GetFloatProp(aObject,aPropertyName)));
  1420. end
  1421. else
  1422. begin
  1423. //Result.JsonValue := TJsonFloatNumber.Create(GetFloatProp(aObject,aPropertyName));
  1424. Result.JsonValue := TJsonFloatNumber.Create(StrToFloat(FloatProperty(aObject,propinfo)));
  1425. end;
  1426. end;
  1427. tkEnumeration,tkBool :
  1428. begin
  1429. if (propinfo.PropType = System.TypeInfo(Boolean)) then
  1430. begin
  1431. Result.JsonValue := TJSONBool.Create(Boolean(GetOrdProp(aObject,aPropertyName)));
  1432. end
  1433. else
  1434. begin
  1435. if fUseEnumNames then Result.JsonValue := TJSONString.Create(GetEnumName(propinfo.PropType,GetOrdProp(aObject,aPropertyName)))
  1436. else Result.JsonValue := TJSONNumber.Create(GetOrdProp(aObject,aPropertyName));
  1437. //Result.JsonValue := TJSONString.Create(aValue.ToString);
  1438. end;
  1439. end;
  1440. tkSet :
  1441. begin
  1442. Result.JsonValue := TJSONString.Create(GetSetProp(aObject,aPropertyName));
  1443. end;
  1444. {$IFNDEF FPC}
  1445. tkRecord :
  1446. begin
  1447. rRec := ctx.GetType(aValue.TypeInfo).AsRecord;
  1448. try
  1449. json := TJSONObject.Create;
  1450. for rField in rRec.GetFields do
  1451. begin
  1452. json.AddPair(Serialize(rField.name,rField.GetValue(aValue.GetReferenceToRawData)));
  1453. end;
  1454. Result.JsonValue := json;
  1455. finally
  1456. ctx.Free;
  1457. end;
  1458. end;
  1459. {$ENDIF}
  1460. tkMethod, tkPointer, tkClassRef ,tkInterface, tkProcedure :
  1461. begin
  1462. //skip these properties
  1463. //FreeAndNil(Result);
  1464. end
  1465. else
  1466. begin
  1467. //raise EJsonDeserializeError.CreateFmt('Not supported type "%s":%d',[aName,Integer(aValue.Kind)]);
  1468. end;
  1469. end;
  1470. if Result.JsonValue = nil then Result.JsonValue := TJSONNull.Create;
  1471. except
  1472. on E : Exception do
  1473. begin
  1474. Result.Free;
  1475. {$IFNDEF FPC}
  1476. raise EJsonSerializeError.CreateFmt('Serialize error class "%s.%s" : %s',[aName,aValue.ToString,e.Message]);
  1477. {$ENDIF}
  1478. end;
  1479. end;
  1480. end;
  1481. {$ENDIF}
  1482. { TJsonSerializer}
  1483. constructor TJsonSerializer.Create(aSerializeLevel: TSerializeLevel; aUseEnumNames : Boolean = True);
  1484. begin
  1485. {$IFDEF FPC}
  1486. if aSerializeLevel = TSerializeLevel.slPublicProperty then raise EJsonSerializeError.Create('FreePascal RTTI only supports published properties');
  1487. {$ENDIF}
  1488. fSerializeLevel := aSerializeLevel;
  1489. fUseEnumNames := aUseEnumNames;
  1490. fUseJsonCaseSense := False;
  1491. fRTTIJson := TRTTIJson.Create(aSerializeLevel,aUseEnumNames);
  1492. fRTTIJson.UseJsonCaseSense := fUseJsonCaseSense;
  1493. end;
  1494. destructor TJsonSerializer.Destroy;
  1495. begin
  1496. fRTTIJson.Free;
  1497. inherited;
  1498. end;
  1499. function TJsonSerializer.JsonToObject(aType: TClass; const aJson: string): TObject;
  1500. var
  1501. json: TJSONObject;
  1502. begin
  1503. {$IFDEF DELPHIRX10_UP}
  1504. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1505. {$ELSE}
  1506. {$IFDEF FPC}
  1507. json := TJSONObject(TJSONObject.ParseJSONValue(aJson,True));
  1508. {$ELSE}
  1509. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1510. {$ENDIF}
  1511. {$ENDIF}
  1512. try
  1513. Result := fRTTIJson.DeserializeClass(aType,json);
  1514. finally
  1515. json.Free;
  1516. end;
  1517. end;
  1518. function TJsonSerializer.JsonToObject(aObject: TObject; const aJson: string): TObject;
  1519. var
  1520. json: TJSONObject;
  1521. begin;
  1522. {$IFDEF DELPHIRX10_UP}
  1523. json := TJSONObject.ParseJSONValue(aJson,True) as TJSONObject;
  1524. {$ELSE}
  1525. {$IFDEF FPC}
  1526. json := TJSONObject(TJSONObject.ParseJSONValue(aJson,True));
  1527. {$ELSE}
  1528. json := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONObject;
  1529. {$ENDIF}
  1530. {$ENDIF}
  1531. try
  1532. Result := fRTTIJson.DeserializeObject(aObject,json);
  1533. finally
  1534. json.Free;
  1535. end;
  1536. end;
  1537. function TJsonSerializer.ObjectToJson(aObject : TObject; aIndent : Boolean = False): string;
  1538. var
  1539. json: TJSONObject;
  1540. begin
  1541. json := fRTTIJson.Serialize(aObject);
  1542. try
  1543. if aIndent then Result := TJsonUtils.JsonFormat(json.ToJSON)
  1544. else Result := json.ToJSON;
  1545. finally
  1546. json.Free;
  1547. end;
  1548. end;
  1549. function TJsonSerializer.ObjectToJsonString(aObject : TObject; aIndent : Boolean = False): string;
  1550. var
  1551. json: TJSONObject;
  1552. begin
  1553. json := fRTTIJson.Serialize(aObject);
  1554. try
  1555. if aIndent then Result := TJsonUtils.JsonFormat(json.ToString)
  1556. else Result := json.ToString;
  1557. finally
  1558. json.Free;
  1559. end;
  1560. end;
  1561. {$IFNDEF FPC}
  1562. function TJsonSerializer.ValueToJson(aValue: TValue; aIndent: Boolean): string;
  1563. var
  1564. json: TJSONObject;
  1565. begin
  1566. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('value',aValue));
  1567. try
  1568. {$IFDEF DELPHI103_UP}
  1569. if aIndent then Result := TJsonUtils.JsonFormat(json.P['value'].ToJSON)
  1570. else Result := json.P['value'].ToJSON;
  1571. {$ELSE}
  1572. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('value').ToJSON)
  1573. else Result := json.GetValue('value').ToJSON;
  1574. {$ENDIF}
  1575. finally
  1576. json.Free;
  1577. end;
  1578. end;
  1579. function TJsonSerializer.ValueToJsonString(aValue: TValue; aIndent: Boolean): string;
  1580. var
  1581. json: TJSONObject;
  1582. begin
  1583. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('value',aValue));
  1584. try
  1585. {$IFDEF DELPHI103_UP}
  1586. if aIndent then Result := TJsonUtils.JsonFormat(json.P['value'].ToJSON)
  1587. else Result := json.P['value'].ToJSON;
  1588. {$ELSE}
  1589. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('value').ToJSON)
  1590. else Result := json.GetValue('value').ToJSON;
  1591. {$ENDIF}
  1592. finally
  1593. json.Free;
  1594. end;
  1595. end;
  1596. function TJsonSerializer.ArrayToJson<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1597. var
  1598. json: TJSONObject;
  1599. begin
  1600. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1601. try
  1602. {$IFDEF DELPHI103_UP}
  1603. if aIndent then Result := TJsonUtils.JsonFormat(json.P['array'].ToJSON)
  1604. else Result := json.P['array'].ToJSON;
  1605. {$ELSE}
  1606. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('array').ToJSON)
  1607. else Result := json.GetValue('array').ToJSON;
  1608. {$ENDIF}
  1609. finally
  1610. json.Free;
  1611. end;
  1612. end;
  1613. function TJsonSerializer.ArrayToJsonString<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1614. var
  1615. json: TJSONObject;
  1616. begin
  1617. json := TJSONObject.Create.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1618. try
  1619. {$IFDEF DELPHI103_UP}
  1620. if aIndent then Result := TJsonUtils.JsonFormat(json.P['array'].ToJSON)
  1621. else Result := json.P['array'].ToJSON;
  1622. {$ELSE}
  1623. if aIndent then Result := TJsonUtils.JsonFormat(json.GetValue('array').ToJSON)
  1624. else Result := json.GetValue('array').ToJSON;
  1625. {$ENDIF}
  1626. finally
  1627. json.Free;
  1628. end;
  1629. end;
  1630. function TJsonSerializer.JsonToArray<T>(const aJson: string): TArray<T>;
  1631. var
  1632. jarray: TJSONArray;
  1633. value : TValue;
  1634. begin;
  1635. {$If Defined(FPC) OR Defined(DELPHIRX10_UP)}
  1636. jarray := TJSONObject.ParseJSONValue(aJson,True) as TJSONArray;
  1637. {$ELSE}
  1638. jarray := TJsonObject.ParseJSONValue(TEncoding.UTF8.GetBytes(aJson),0,True) as TJSONArray;
  1639. {$ENDIF}
  1640. try
  1641. value := fRTTIJson.DeserializeDynArray(PTypeInfo(TypeInfo(TArray<T>)),nil,jarray);
  1642. Result := value.AsType<TArray<T>>;
  1643. finally
  1644. jarray.Free;
  1645. end;
  1646. end;
  1647. {$ELSE}
  1648. function TJsonSerializer.ValueToJson(aValue: TValue; aIndent: Boolean): string;
  1649. var
  1650. json: TJSONObject;
  1651. begin
  1652. json := TJSONObject.Create;
  1653. json.AddPair(fRTTIJson.Serialize('value',aValue));
  1654. try
  1655. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('value').ToJSON)
  1656. else Result := json.Get('value').ToJSON;
  1657. finally
  1658. json.Free;
  1659. end;
  1660. end;
  1661. function TJsonSerializer.ValueToJsonString(aValue: TValue; aIndent: Boolean): string;
  1662. var
  1663. json: TJSONObject;
  1664. begin
  1665. json := TJSONObject.Create;
  1666. json.AddPair(fRTTIJson.Serialize('value',aValue));
  1667. try
  1668. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('value').ToString)
  1669. else Result := json.Get('value').ToString;
  1670. finally
  1671. json.Free;
  1672. end;
  1673. end;
  1674. function TJsonSerializer.ArrayToJson<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1675. var
  1676. json: TJSONObject;
  1677. begin
  1678. json := TJSONObject.Create;
  1679. json.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1680. try
  1681. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('array').ToJSON)
  1682. else Result := json.Get('array').ToJSON;
  1683. finally
  1684. json.Free;
  1685. end;
  1686. end;
  1687. function TJsonSerializer.ArrayToJsonString<T>(aArray: TArray<T>; aIndent: Boolean): string;
  1688. var
  1689. json: TJSONObject;
  1690. begin
  1691. json := TJSONObject.Create;
  1692. json.AddPair(fRTTIJson.Serialize('array',TValue.From<TArray<T>>(aArray)));
  1693. try
  1694. if aIndent then Result := TJsonUtils.JsonFormat(json.Get('array').ToString)
  1695. else Result := json.Get('array').ToString;
  1696. finally
  1697. json.Free;
  1698. end;
  1699. end;
  1700. {$ENDIF}
  1701. procedure TJsonSerializer.SetUseEnumNames(const Value: Boolean);
  1702. begin
  1703. fUseEnumNames := Value;
  1704. if Assigned(fRTTIJson) then fRTTIJson.UseEnumNames := Value;
  1705. end;
  1706. procedure TJsonSerializer.SetUseJsonCaseSense(const Value: Boolean);
  1707. begin
  1708. fUseJsonCaseSense := Value;
  1709. if Assigned(fRTTIJson) then fRTTIJson.UseJsonCaseSense := Value;
  1710. end;
  1711. {$IFNDEF FPC}
  1712. { TCommentProperty }
  1713. constructor TCommentProperty.Create(const aComment: string);
  1714. begin
  1715. fComment := aComment;
  1716. end;
  1717. { TCustomNameProperty }
  1718. constructor TCustomNameProperty.Create(const aName: string);
  1719. begin
  1720. fName := aName;
  1721. end;
  1722. {$ENDIF}
  1723. end.