Quick.Json.Serializer.pas 56 KB

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