Quick.Json.Serializer.pas 56 KB

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